first commit

This commit is contained in:
Zenn 2023-08-06 18:14:49 +02:00
commit c591b2c272
50 changed files with 2650 additions and 0 deletions

274
Examples/snake/src/lib.rs Normal file
View 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;
}
}