addded change into screens and powerup

master
kirbylife 2020-09-06 20:22:59 -05:00
parent 6f978c4cb9
commit 2c62ed12f6
2 changed files with 516 additions and 101 deletions

View File

@ -4,5 +4,7 @@ version = "0.1.0"
authors = ["kirbylife <kirbylife@protonmail.com>"] authors = ["kirbylife <kirbylife@protonmail.com>"]
[dependencies] [dependencies]
# heapless = "*"
# fixedvec = "*"
ruduino = "0.2.5" ruduino = "0.2.5"
avr-std-stub = "1.0" avr-std-stub = "1.0"

View File

@ -60,6 +60,7 @@ enum Direction {
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
struct Player { struct Player {
position: Position, position: Position,
old_position: Position,
size: Size, size: Size,
force: i8, force: i8,
speed: f32, speed: f32,
@ -70,7 +71,9 @@ impl Player {
fn new() -> Self { fn new() -> Self {
Player { Player {
position: Position { x: 2, y: 30 }, position: Position { x: 2, y: 30 },
old_position: Position { x: 2, y: 30 },
size: Size { size: Size {
// width: 5,
width: 3, width: 3,
height: 6, height: 6,
}, },
@ -82,6 +85,9 @@ impl Player {
} }
fn collide(&self, wall: &Wall) -> Option<Direction> { fn collide(&self, wall: &Wall) -> Option<Direction> {
if wall.size.width == 0 || wall.size.height == 0 {
return None;
}
let is_colliding = self.position.x < wall.position.x + wall.size.width let is_colliding = self.position.x < wall.position.x + wall.size.width
&& self.position.x + self.size.width > wall.position.x && self.position.x + self.size.width > wall.position.x
&& self.position.y < wall.position.y + wall.size.height && self.position.y < wall.position.y + wall.size.height
@ -100,6 +106,85 @@ impl Player {
} else { } else {
None None
} }
// =========== New Function ===========
// if self.position.x + self.size.width > wall.position.x
// && self.position.x < wall.position.x + wall.size.width
// && self.position.y + self.size.height > wall.position.y
// && self.position.y < wall.position.y + wall.size.height
// {
// if self.jumping && self.force <= 0 {
// Some(Direction::Down)
// } else {
// Some(Direction::Up)
// }
// } else if self.position.x + self.size.width > wall.position.x
// && self.position.x < wall.position.x + wall.size.width
// && self.position.y + self.size.height > wall.position.y
// && self.position.y < wall.position.y + wall.size.height
// {
// if self.position.x < wall.position.x {
// Some(Direction::Left)
// } else {
// Some(Direction::Up)
// }
// } else {
// None
// }
}
fn draw(&mut self) {
// draw_player(&player, &old_player);
// old_player = player.clone();
if self.position == self.old_position {
return;
}
for b in [
'|' as u8,
2,
// self.old_position.x as u8 + 1,
// self.old_position.y as u8,
// self.size.width as u8 - 2,
// self.size.height as u8 - 1,
self.old_position.x as u8,
self.old_position.y as u8,
self.size.width as u8,
self.size.height as u8 - 1,
GREEN,
]
.iter()
{
serial::transmit(*b);
}
for b in [
'|' as u8,
2,
// self.position.x as u8 + 1,
// self.position.y as u8,
// self.size.width as u8 - 2,
// self.size.height as u8 - 1,
self.position.x as u8,
self.position.y as u8,
self.size.width as u8,
self.size.height as u8 - 1,
RED,
]
.iter()
{
serial::transmit(*b);
}
self.old_position = self.position.clone();
}
fn powerup(&mut self, growup: bool) {
if growup {
self.position.y = self.position.y - 4;
self.size.height = self.size.height + 4;
self.powered = true;
} else {
self.position.y = self.position.y + 4;
self.size.height = self.size.height - 4;
self.powered = false;
}
} }
} }
@ -107,6 +192,10 @@ impl Player {
enum WallType { enum WallType {
Solid, Solid,
Breakable, Breakable,
Secret,
PowerupBox,
VerticalPipe,
Powerup,
} }
#[derive(Clone)] #[derive(Clone)]
@ -119,13 +208,170 @@ struct Wall {
impl Wall { impl Wall {
fn new(size: Size, position: Position, wall_type: WallType) -> Self { fn new(size: Size, position: Position, wall_type: WallType) -> Self {
if wall_type == WallType::Secret {
Wall {
position: position,
size: size,
wall_type: wall_type,
visible: false,
}
} else {
Wall {
position: position,
size: size,
wall_type: wall_type,
visible: true,
}
}
}
fn powerup(position: Position) -> Self {
Wall { Wall {
position: position, position: Position {
size: size, x: position.x + 1,
wall_type: wall_type, y: position.y,
},
size: Size {
width: 3,
height: 5,
},
wall_type: WallType::Powerup,
visible: true, visible: true,
} }
} }
fn useless() -> Self {
Wall {
position: Position { x: 0, y: 0 },
size: Size {
width: 0,
height: 0,
},
wall_type: WallType::Solid,
visible: false,
}
}
fn draw(&self) {
if self.size.width == 0 || self.size.height == 0 {
return;
}
for b in [
'|' as u8,
2,
self.position.x as u8,
self.position.y as u8,
self.size.width as u8,
self.size.height as u8,
if self.wall_type == WallType::Powerup {
RED
} else {
BLACK
},
]
.iter()
{
serial::transmit(*b);
}
match self.wall_type {
WallType::Breakable | WallType::PowerupBox => {
for b in [
'|' as u8,
2,
self.position.x as u8 + 1,
self.position.y as u8 + 2,
self.size.width as u8 - 2,
1,
GREEN,
]
.iter()
{
serial::transmit(*b);
}
}
WallType::VerticalPipe => {
for b in [
'|' as u8,
2,
self.position.x as u8 - 1,
self.position.y as u8,
self.size.width as u8 + 2,
4,
BLACK,
]
.iter()
{
serial::transmit(*b);
}
}
WallType::Powerup => {
for b in [
// First decoration
'|' as u8,
2,
self.position.x as u8 - 1,
self.position.y as u8 + 1,
5,
1,
RED,
// Second decoration
'|' as u8,
2,
self.position.x as u8 - 2,
self.position.y as u8 + 2,
7,
1,
RED,
]
.iter()
{
serial::transmit(*b);
}
}
_ => {}
}
}
fn erase(&self) {
match self.wall_type {
WallType::Powerup => {
for b in [
'|' as u8,
2,
self.position.x as u8 - 2,
self.position.y as u8,
7,
5,
GREEN,
]
.iter()
{
serial::transmit(*b);
}
}
_ => {
for b in [
'|' as u8,
2,
self.position.x as u8,
self.position.y as u8,
self.size.width as u8,
self.size.height as u8,
GREEN,
]
.iter()
{
serial::transmit(*b);
}
}
}
}
fn destroy(&mut self) {
self.visible = false;
self.erase();
}
} }
#[no_mangle] #[no_mangle]
@ -138,17 +384,19 @@ pub unsafe extern "C" fn main() -> ! {
DDRD::set_mask_raw(HIGH); DDRD::set_mask_raw(HIGH);
PORTD::unset_mask_raw(HIGH); PORTD::unset_mask_raw(HIGH);
let mut step = 0; let mut step: u8 = 0;
let mut player = Player::new(); let mut player = Player::new();
let mut walls: [Wall; 8] = [ let screen1: [Wall; 8] = [
// Floor
Wall::new( Wall::new(
Size { Size {
width: 120, width: 120,
height: 5, height: 4,
}, },
Position { x: 0, y: 54 }, Position { x: 0, y: 55 },
WallType::Solid, WallType::Solid,
), ),
// Individual block left
Wall::new( Wall::new(
Size { Size {
width: 5, width: 5,
@ -157,14 +405,16 @@ pub unsafe extern "C" fn main() -> ! {
Position { x: 50, y: 35 }, Position { x: 50, y: 35 },
WallType::Solid, WallType::Solid,
), ),
// Powerup block
Wall::new( Wall::new(
Size { Size {
width: 5, width: 5,
height: 5, height: 5,
}, },
Position { x: 70, y: 35 }, Position { x: 70, y: 35 },
WallType::Breakable, WallType::PowerupBox,
), ),
// Middle breakable block
Wall::new( Wall::new(
Size { Size {
width: 5, width: 5,
@ -173,6 +423,7 @@ pub unsafe extern "C" fn main() -> ! {
Position { x: 80, y: 35 }, Position { x: 80, y: 35 },
WallType::Breakable, WallType::Breakable,
), ),
// Right breakable block
Wall::new( Wall::new(
Size { Size {
width: 5, width: 5,
@ -181,6 +432,7 @@ pub unsafe extern "C" fn main() -> ! {
Position { x: 90, y: 35 }, Position { x: 90, y: 35 },
WallType::Breakable, WallType::Breakable,
), ),
// left middle solid block
Wall::new( Wall::new(
Size { Size {
width: 5, width: 5,
@ -189,6 +441,7 @@ pub unsafe extern "C" fn main() -> ! {
Position { x: 80, y: 20 }, Position { x: 80, y: 20 },
WallType::Solid, WallType::Solid,
), ),
// right middle solid block
Wall::new( Wall::new(
Size { Size {
width: 5, width: 5,
@ -197,6 +450,7 @@ pub unsafe extern "C" fn main() -> ! {
Position { x: 85, y: 35 }, Position { x: 85, y: 35 },
WallType::Solid, WallType::Solid,
), ),
// Upper solid block
Wall::new( Wall::new(
Size { Size {
width: 5, width: 5,
@ -206,32 +460,246 @@ pub unsafe extern "C" fn main() -> ! {
WallType::Solid, WallType::Solid,
), ),
]; ];
let screen2: [Wall; 8] = [
// Floor
Wall::new(
Size {
width: 120,
height: 4,
},
Position { x: 0, y: 55 },
WallType::Solid,
),
// Pipe 1
Wall::new(
Size {
width: 5,
height: 10,
},
Position { x: 35, y: 45 },
WallType::VerticalPipe,
),
Wall::new(
Size {
width: 0,
height: 5,
},
Position { x: 34, y: 45 },
WallType::Solid,
),
// Pipe 2
Wall::new(
Size {
width: 5,
height: 15,
},
Position { x: 65, y: 40 },
WallType::VerticalPipe,
),
Wall::new(
Size {
width: 0,
height: 5,
},
Position { x: 64, y: 40 },
WallType::Solid,
),
// Pipe 3
Wall::new(
Size {
width: 5,
height: 20,
},
Position { x: 95, y: 35 },
WallType::VerticalPipe,
),
Wall::new(
Size {
width: 0,
height: 5,
},
Position { x: 94, y: 35 },
WallType::Solid,
),
// Extra wall useless
Wall::useless(),
];
let screen3: [Wall; 8] = [
// Floor 1
Wall::new(
Size {
width: 80,
height: 4,
},
Position { x: 0, y: 55 },
WallType::Solid,
),
// floor 2
Wall::new(
Size {
width: 25,
height: 4,
},
Position { x: 95, y: 55 },
WallType::Solid,
),
// Pipe
Wall::new(
Size {
width: 5,
height: 20,
},
Position { x: 30, y: 35 },
WallType::VerticalPipe,
),
// Invisible block
Wall::new(
Size {
width: 5,
height: 5,
},
Position { x: 65, y: 30 },
WallType::Secret,
),
// Extra walls useless
Wall::useless(),
Wall::useless(),
Wall::useless(),
Wall::useless(),
];
let screen4: [Wall; 8] = [
// Floor 1
Wall::new(
Size {
width: 100,
height: 4,
},
Position { x: 0, y: 55 },
WallType::Solid,
),
// Second floor
Wall::new(
Size {
width: 5,
height: 4,
},
Position { x: 115, y: 55 },
WallType::Solid,
),
// Powerup block
Wall::new(
Size {
width: 5,
height: 5,
},
Position { x: 50, y: 35 },
WallType::Breakable,
),
// Middle breakable block
Wall::new(
Size {
width: 5,
height: 5,
},
Position { x: 55, y: 35 },
WallType::PowerupBox,
),
// Right breakable block
Wall::new(
Size {
width: 5,
height: 5,
},
Position { x: 60, y: 35 },
WallType::Breakable,
),
// Up big block
Wall::new(
Size {
width: 45,
height: 5,
},
Position { x: 65, y: 15 },
WallType::Solid,
),
// Extra walls useless
Wall::useless(),
Wall::useless(),
];
let map: [[Wall; 8]; 4] = [screen1, screen2, screen3, screen4];
clear(); clear();
let mut old_player = player.clone(); let mut level: usize = 0;
let mut last_wall_collisioned: Option<Wall> = None; let mut walls = map[level].clone();
// As the original SMB, in logic there will only be one powerup at a time
let mut powerup: Option<Wall> = None;
let mut powerup_painted = true;
for wall in walls.iter() { for wall in walls.iter() {
if wall.visible { if wall.visible {
draw_wall(wall); wall.draw();
} }
} }
loop { loop {
// clear(); // clear();
draw_player(&player, &old_player);
old_player = player.clone();
// If the player fall of the map, restart
if player.position.y > 70 { if player.position.y > 70 {
player = Player::new(); player = Player::new();
continue; continue;
} }
// level scroll logic
if player.position.x > 120 {
level += 1;
if level >= map.len() {
level -= 1;
player.position.x = 120;
continue;
}
walls = map[level].clone();
player.position.x = 1;
clear();
for wall in walls.iter() {
if wall.visible {
wall.draw();
}
}
continue;
}
if player.position.x < 0 && level > 0 {
level -= 1;
player.position.x = 120;
walls = map[level].clone();
clear();
for wall in walls.iter() {
if wall.visible {
wall.draw();
}
}
continue;
}
match powerup {
Some(ref powerup_) => {
if player.collide(&powerup_).is_some() {
powerup_.erase();
powerup = None;
player.powerup(true);
} else {
if !powerup_painted {
powerup_.draw();
powerup_painted = true;
}
}
}
_ => {}
}
let mut fall = true; let mut fall = true;
// Static wall behavior // Static wall behavior
let mut horizontal_collision: Option<Direction> = None;
for wall in &mut walls { for wall in &mut walls {
if wall.visible { if wall.visible || wall.wall_type == WallType::Secret {
match player.collide(wall) { match player.collide(wall) {
Some(Direction::Up) => { Some(Direction::Up) => {
player.jumping = false; player.jumping = false;
@ -241,17 +709,37 @@ pub unsafe extern "C" fn main() -> ! {
} }
player.position.y += 1; player.position.y += 1;
fall = false; fall = false;
draw_wall(&wall); wall.draw();
} }
Some(Direction::Down) => { Some(Direction::Down) => {
player.force = 0; player.force = 0;
player.position.y += 1; player.position.y += 1;
fall = true; fall = true;
if wall.wall_type == WallType::Breakable { match wall.wall_type {
delete_wall(&wall); WallType::Breakable => {
wall.visible = false; if player.powered {
} else { wall.destroy();
draw_wall(&wall); } else {
wall.draw();
}
}
WallType::PowerupBox => {
let powerup_ = Wall::powerup(Position {
x: wall.position.x,
y: wall.position.y - 5,
});
powerup = Some(powerup_);
powerup_painted = false;
wall.wall_type = WallType::Solid;
}
WallType::Secret => {
if player.force < 0 {
wall.visible = true;
wall.wall_type = WallType::Solid;
wall.draw();
}
}
_ => wall.draw(),
} }
} }
Some(dir) => { Some(dir) => {
@ -267,8 +755,8 @@ pub unsafe extern "C" fn main() -> ! {
} else { } else {
player.position.x -= 1; player.position.x -= 1;
} }
horizontal_collision = Some(dir); wall.draw();
draw_wall(&wall); // draw_wall(&wall);
} }
// None => fall = true, // None => fall = true,
None => {} None => {}
@ -276,6 +764,8 @@ pub unsafe extern "C" fn main() -> ! {
} }
} }
player.draw();
// Gravity control // Gravity control
// if the variable `fall` is true it's because all the logic of // if the variable `fall` is true it's because all the logic of
// The platforms doesn't stop the fallen of the character // The platforms doesn't stop the fallen of the character
@ -339,7 +829,7 @@ pub unsafe extern "C" fn main() -> ! {
} }
} }
fn delay(cycles: u32) { fn _delay(cycles: u32) {
for _ in 0..(1_600 * cycles) { for _ in 0..(1_600 * cycles) {
unsafe { llvm_asm!("" :::: "volatile") } unsafe { llvm_asm!("" :::: "volatile") }
} }
@ -351,83 +841,6 @@ fn clear() {
} }
} }
fn draw_player(player: &Player, old_player: &Player) {
if player == old_player {
return;
}
for b in [
'|' as u8,
2,
old_player.position.x as u8,
old_player.position.y as u8,
old_player.size.width as u8,
old_player.size.height as u8 - 1,
GREEN,
]
.iter()
{
serial::transmit(*b);
}
for b in [
'|' as u8,
2,
player.position.x as u8,
player.position.y as u8,
player.size.width as u8,
player.size.height as u8 - 1,
RED,
]
.iter()
{
serial::transmit(*b);
}
}
fn draw_wall(wall: &Wall) {
for b in [
'|' as u8,
2,
wall.position.x as u8,
wall.position.y as u8,
wall.size.width as u8,
wall.size.height as u8,
BLACK,
]
.iter()
{
serial::transmit(*b);
}
if wall.wall_type == WallType::Breakable {
for b in [
'|' as u8,
1,
wall.position.x as u8 + 2,
wall.position.y as u8 + 2,
GREEN,
]
.iter()
{
serial::transmit(*b);
}
}
}
fn delete_wall(wall: &Wall) {
for b in [
'|' as u8,
2,
wall.position.x as u8,
wall.position.y as u8,
wall.size.width as u8,
wall.size.height as u8,
GREEN,
]
.iter()
{
serial::transmit(*b);
}
}
fn serial_start() { fn serial_start() {
serial::Serial::new(UBRR) serial::Serial::new(UBRR)
.character_size(serial::CharacterSize::EightBits) .character_size(serial::CharacterSize::EightBits)