first commit
This commit is contained in:
commit
c591b2c272
50 changed files with 2650 additions and 0 deletions
12
Examples/snake/Cargo.toml
Normal file
12
Examples/snake/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "snake"
|
||||
version = "0.1.0"
|
||||
authors = ["ZennDev <zenndev@protonmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
arduboy-rust = "1.0.0"
|
274
Examples/snake/src/lib.rs
Normal file
274
Examples/snake/src/lib.rs
Normal file
|
@ -0,0 +1,274 @@
|
|||
#![no_std]
|
||||
use arduboy_rust::prelude::*;
|
||||
|
||||
static mut MEM: u8 = 0;
|
||||
static SCORE: EEPROM = EEPROM::new(100);
|
||||
|
||||
const WORLD_WIDTH: u8 = 32;
|
||||
const WORLD_HEIGHT: u8 = 16;
|
||||
const SCALE_FACTOR: u8 = 4;
|
||||
#[allow(dead_code)]
|
||||
enum State {
|
||||
Title,
|
||||
Game,
|
||||
Win,
|
||||
GameOver,
|
||||
Reset,
|
||||
Pause,
|
||||
}
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
enum Direction {
|
||||
Up,
|
||||
Left,
|
||||
Down,
|
||||
Right,
|
||||
}
|
||||
struct Snake {
|
||||
game_state: State,
|
||||
points: u8,
|
||||
len: u8,
|
||||
pos: [(u8, u8); 255 as usize],
|
||||
next_food: (u8, u8),
|
||||
delta_time: u8,
|
||||
direction: Direction,
|
||||
last_direction: Direction,
|
||||
}
|
||||
impl Snake {
|
||||
fn movement(&mut self) {
|
||||
for i in 0..(self.len - 1) as usize {
|
||||
self.pos[i] = self.pos[i + 1];
|
||||
}
|
||||
let (x, y) = self.pos[(self.len - 1) as usize];
|
||||
match self.direction {
|
||||
Direction::Up => {
|
||||
self.pos[(self.len - 1) as usize] = (x, y - 1);
|
||||
}
|
||||
Direction::Left => {
|
||||
self.pos[(self.len - 1) as usize] = (x - 1, y);
|
||||
}
|
||||
Direction::Down => {
|
||||
self.pos[(self.len - 1) as usize] = (x, y + 1);
|
||||
}
|
||||
Direction::Right => {
|
||||
self.pos[(self.len - 1) as usize] = (x + 1, y);
|
||||
}
|
||||
}
|
||||
self.last_direction = self.direction;
|
||||
}
|
||||
unsafe fn get_new_dir(&mut self) {
|
||||
if UP.just_pressed() && self.last_direction != Direction::Down {
|
||||
self.direction = Direction::Up
|
||||
}
|
||||
if LEFT.just_pressed() && self.last_direction != Direction::Right {
|
||||
self.direction = Direction::Left
|
||||
}
|
||||
if DOWN.just_pressed() && self.last_direction != Direction::Up {
|
||||
self.direction = Direction::Down
|
||||
}
|
||||
if RIGHT.just_pressed() && self.last_direction != Direction::Left {
|
||||
self.direction = Direction::Right
|
||||
}
|
||||
}
|
||||
fn new_food(&mut self) {
|
||||
self.next_food.0 = 0;
|
||||
self.next_food.1 = 0;
|
||||
while self.next_food.0 == 0 && self.next_food.1 == 0 {
|
||||
self.next_food.0 = random_between(2, (WORLD_WIDTH - 2).into()) as u8;
|
||||
self.next_food.1 = random_between(2, (WORLD_HEIGHT - 2).into()) as u8;
|
||||
for i in 0..(self.len) as usize {
|
||||
if self.pos[i] == self.next_food {
|
||||
self.next_food.0 = 0;
|
||||
self.next_food.1 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe fn render(&self) {
|
||||
arduboy.draw_circle(
|
||||
((self.next_food.0 * SCALE_FACTOR) + SCALE_FACTOR / 4)
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
((self.next_food.1 * SCALE_FACTOR) + SCALE_FACTOR / 4)
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
SCALE_FACTOR / 4,
|
||||
Color::White,
|
||||
);
|
||||
|
||||
self.pos.iter().enumerate().for_each(|(i, p)| {
|
||||
if i == (self.len) as usize {
|
||||
return;
|
||||
}
|
||||
if *p == (0, 0) {
|
||||
return;
|
||||
}
|
||||
arduboy.fill_rect(
|
||||
(p.0 as u8 * SCALE_FACTOR).try_into().unwrap(),
|
||||
(p.1 as u8 * SCALE_FACTOR).try_into().unwrap(),
|
||||
SCALE_FACTOR / 2,
|
||||
SCALE_FACTOR / 2,
|
||||
Color::White,
|
||||
);
|
||||
});
|
||||
}
|
||||
unsafe fn init(&mut self) {
|
||||
self.points = 0;
|
||||
self.len = 3;
|
||||
self.direction = Direction::Right;
|
||||
self.last_direction = Direction::Left;
|
||||
self.pos = [(0, 0); 255 as usize];
|
||||
self.pos[0] = (3, 4);
|
||||
self.pos[1] = (4, 4);
|
||||
self.pos[2] = (5, 4);
|
||||
}
|
||||
unsafe fn boarder(&self) {
|
||||
for x in 0..WORLD_WIDTH as usize {
|
||||
for y in 0..WORLD_HEIGHT as usize {
|
||||
if x == 0
|
||||
|| y == 0
|
||||
|| x == (WORLD_WIDTH - 1) as usize
|
||||
|| y == (WORLD_HEIGHT - 1) as usize
|
||||
{
|
||||
let scale: u8 = 2;
|
||||
if self.delta_time % 20 == 0 {
|
||||
//scale = 1;
|
||||
};
|
||||
arduboy.fill_rect(
|
||||
(x as u8 * SCALE_FACTOR + scale / 2).try_into().unwrap(),
|
||||
(y as u8 * SCALE_FACTOR + scale / 2).try_into().unwrap(),
|
||||
SCALE_FACTOR / scale,
|
||||
SCALE_FACTOR / scale,
|
||||
Color::White,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fn collision_check(&mut self) {
|
||||
let (x, y) = self.pos[(self.len - 1) as usize];
|
||||
if x == 0 || x == 31 || y == 0 || y == 15 {
|
||||
self.game_state = State::GameOver;
|
||||
}
|
||||
self.pos.iter().enumerate().for_each(|(i, p)| {
|
||||
if p == &(x, y) && i != (self.len - 1) as usize {
|
||||
self.game_state = State::GameOver;
|
||||
}
|
||||
});
|
||||
if self.pos[(self.len - 1) as usize] == self.next_food {
|
||||
self.points += 1;
|
||||
self.new_food();
|
||||
self.pos[self.len as usize] = self.pos[(self.len - 1) as usize];
|
||||
self.len += 1;
|
||||
sound.tone(0xff, 0x3f);
|
||||
}
|
||||
}
|
||||
}
|
||||
#[allow(non_upper_case_globals)]
|
||||
static mut snake: Snake = Snake {
|
||||
game_state: State::Reset,
|
||||
len: 3,
|
||||
points: 0,
|
||||
pos: [(0, 0); 255 as usize],
|
||||
next_food: (0, 0),
|
||||
delta_time: 0,
|
||||
direction: Direction::Right,
|
||||
last_direction: Direction::Left,
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn setup() {
|
||||
arduboy.begin();
|
||||
SCORE.init();
|
||||
arduboy.init_random_seed();
|
||||
arduboy.set_frame_rate(60);
|
||||
arduboy.clear();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[export_name = "loop"]
|
||||
pub unsafe extern "C" fn loop_() {
|
||||
if !arduboy.next_frame() {
|
||||
return;
|
||||
}
|
||||
arduboy.poll_buttons();
|
||||
arduboy.clear();
|
||||
match snake.game_state {
|
||||
State::Reset => {
|
||||
snake.init();
|
||||
snake.new_food();
|
||||
snake.game_state = State::Title;
|
||||
}
|
||||
State::Title => {
|
||||
arduboy.set_cursor(0, 0);
|
||||
arduboy.set_text_size(2);
|
||||
arduboy.print(&b"RustySnake\n\0"[..]);
|
||||
arduboy.set_text_size(1);
|
||||
arduboy.print(&b"\nControls: \nB for Pause\nA&B for reset\n\0"[..]);
|
||||
arduboy.print(&b"\nZennDev 2023\n\0"[..]);
|
||||
if A.just_pressed() {
|
||||
snake.game_state = State::Game;
|
||||
}
|
||||
}
|
||||
State::Game => {
|
||||
snake.get_new_dir();
|
||||
if snake.delta_time % 10 == 0 {
|
||||
snake.movement();
|
||||
snake.collision_check();
|
||||
};
|
||||
snake.render();
|
||||
snake.boarder();
|
||||
if B.just_pressed() {
|
||||
sound.tone(800, 100);
|
||||
snake.game_state = State::Pause;
|
||||
}
|
||||
}
|
||||
State::Win => (),
|
||||
State::Pause => {
|
||||
let msg = &b"[ Break ]\0"[..];
|
||||
let l = msg.len() as u8 * FONT_SIZE / 2;
|
||||
arduboy.set_cursor(
|
||||
((WIDTH / 2) as u16 - l as u16).try_into().unwrap(),
|
||||
((HEIGHT / 2) as u16).try_into().unwrap(),
|
||||
);
|
||||
snake.render();
|
||||
snake.boarder();
|
||||
arduboy.print(msg);
|
||||
if B.just_pressed() {
|
||||
snake.game_state = State::Game;
|
||||
sound.tone(800, 100);
|
||||
}
|
||||
}
|
||||
State::GameOver => {
|
||||
SCORE.get(&mut MEM);
|
||||
if MEM == 255 {
|
||||
MEM = 0;
|
||||
}
|
||||
if snake.points > MEM {
|
||||
SCORE.put(snake.points);
|
||||
}
|
||||
|
||||
arduboy.set_cursor(0, 0);
|
||||
arduboy.print(&b"Game Over!\0"[..]);
|
||||
arduboy.print(&b"\n\n\0"[..]);
|
||||
arduboy.print(&b"Score: \0"[..]);
|
||||
arduboy.print(snake.points as u16);
|
||||
arduboy.print(&b"\nHigh Score: \0"[..]);
|
||||
arduboy.print(MEM as u16);
|
||||
arduboy.print(&b"\n\n\0"[..]);
|
||||
arduboy.print(&b"Press A to Play Again\0"[..]);
|
||||
|
||||
if A.just_pressed() {
|
||||
snake.game_state = State::Reset;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (A | B).pressed() {
|
||||
snake.game_state = State::Reset;
|
||||
}
|
||||
arduboy.display();
|
||||
if snake.delta_time == 60 {
|
||||
snake.delta_time = 1
|
||||
} else {
|
||||
snake.delta_time += 1;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue