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>"]
[dependencies]
# heapless = "*"
# fixedvec = "*"
ruduino = "0.2.5"
avr-std-stub = "1.0"

View File

@ -60,6 +60,7 @@ enum Direction {
#[derive(Clone, PartialEq)]
struct Player {
position: Position,
old_position: Position,
size: Size,
force: i8,
speed: f32,
@ -70,7 +71,9 @@ impl Player {
fn new() -> Self {
Player {
position: Position { x: 2, y: 30 },
old_position: Position { x: 2, y: 30 },
size: Size {
// width: 5,
width: 3,
height: 6,
},
@ -82,6 +85,9 @@ impl Player {
}
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
&& self.position.x + self.size.width > wall.position.x
&& self.position.y < wall.position.y + wall.size.height
@ -100,6 +106,85 @@ impl Player {
} else {
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 {
Solid,
Breakable,
Secret,
PowerupBox,
VerticalPipe,
Powerup,
}
#[derive(Clone)]
@ -119,13 +208,170 @@ struct Wall {
impl Wall {
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 {
position: position,
size: size,
wall_type: wall_type,
position: Position {
x: position.x + 1,
y: position.y,
},
size: Size {
width: 3,
height: 5,
},
wall_type: WallType::Powerup,
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]
@ -138,17 +384,19 @@ pub unsafe extern "C" fn main() -> ! {
DDRD::set_mask_raw(HIGH);
PORTD::unset_mask_raw(HIGH);
let mut step = 0;
let mut step: u8 = 0;
let mut player = Player::new();
let mut walls: [Wall; 8] = [
let screen1: [Wall; 8] = [
// Floor
Wall::new(
Size {
width: 120,
height: 5,
height: 4,
},
Position { x: 0, y: 54 },
Position { x: 0, y: 55 },
WallType::Solid,
),
// Individual block left
Wall::new(
Size {
width: 5,
@ -157,14 +405,16 @@ pub unsafe extern "C" fn main() -> ! {
Position { x: 50, y: 35 },
WallType::Solid,
),
// Powerup block
Wall::new(
Size {
width: 5,
height: 5,
},
Position { x: 70, y: 35 },
WallType::Breakable,
WallType::PowerupBox,
),
// Middle breakable block
Wall::new(
Size {
width: 5,
@ -173,6 +423,7 @@ pub unsafe extern "C" fn main() -> ! {
Position { x: 80, y: 35 },
WallType::Breakable,
),
// Right breakable block
Wall::new(
Size {
width: 5,
@ -181,6 +432,7 @@ pub unsafe extern "C" fn main() -> ! {
Position { x: 90, y: 35 },
WallType::Breakable,
),
// left middle solid block
Wall::new(
Size {
width: 5,
@ -189,6 +441,7 @@ pub unsafe extern "C" fn main() -> ! {
Position { x: 80, y: 20 },
WallType::Solid,
),
// right middle solid block
Wall::new(
Size {
width: 5,
@ -197,6 +450,7 @@ pub unsafe extern "C" fn main() -> ! {
Position { x: 85, y: 35 },
WallType::Solid,
),
// Upper solid block
Wall::new(
Size {
width: 5,
@ -206,32 +460,246 @@ pub unsafe extern "C" fn main() -> ! {
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();
let mut old_player = player.clone();
let mut last_wall_collisioned: Option<Wall> = None;
let mut level: usize = 0;
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() {
if wall.visible {
draw_wall(wall);
wall.draw();
}
}
loop {
// clear();
draw_player(&player, &old_player);
old_player = player.clone();
// If the player fall of the map, restart
if player.position.y > 70 {
player = Player::new();
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;
// Static wall behavior
let mut horizontal_collision: Option<Direction> = None;
for wall in &mut walls {
if wall.visible {
if wall.visible || wall.wall_type == WallType::Secret {
match player.collide(wall) {
Some(Direction::Up) => {
player.jumping = false;
@ -241,17 +709,37 @@ pub unsafe extern "C" fn main() -> ! {
}
player.position.y += 1;
fall = false;
draw_wall(&wall);
wall.draw();
}
Some(Direction::Down) => {
player.force = 0;
player.position.y += 1;
fall = true;
if wall.wall_type == WallType::Breakable {
delete_wall(&wall);
wall.visible = false;
} else {
draw_wall(&wall);
match wall.wall_type {
WallType::Breakable => {
if player.powered {
wall.destroy();
} 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) => {
@ -267,8 +755,8 @@ pub unsafe extern "C" fn main() -> ! {
} else {
player.position.x -= 1;
}
horizontal_collision = Some(dir);
draw_wall(&wall);
wall.draw();
// draw_wall(&wall);
}
// None => fall = true,
None => {}
@ -276,6 +764,8 @@ pub unsafe extern "C" fn main() -> ! {
}
}
player.draw();
// Gravity control
// if the variable `fall` is true it's because all the logic of
// 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) {
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() {
serial::Serial::new(UBRR)
.character_size(serial::CharacterSize::EightBits)