survivor

graphical action game for the linux terminal
git clone https://git.ce9e.org/survivor.git

commit
79551b82c2dab0beb81bb0d7cf06b4ede6ae2d04
parent
3f73a2c0cd3e2ad895a8f2537d9b17a367fec2c1
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2023-02-18 22:20
use struct for player

Diffstat

M src/main.rs 170 ++++++++++++++++++++++++++++++++++---------------------------

1 files changed, 96 insertions, 74 deletions


diff --git a/src/main.rs b/src/main.rs

@@ -107,6 +107,25 @@ struct Diamond {
  107   107     pub y: f32,
  108   108 }
  109   109 
   -1   110 struct Player {
   -1   111     pub x: f32,
   -1   112     pub y: f32,
   -1   113     pub dir: Dir,
   -1   114     pub face: Dir,
   -1   115     pub speed: f32,
   -1   116     pub size: f32,
   -1   117     pub health: f32,
   -1   118     pub health_max: f32,
   -1   119     pub health_recover: f32,
   -1   120     pub power: f32,
   -1   121     pub damage_radius: f32,
   -1   122     pub diamond_radius: f32,
   -1   123     pub xp: usize,
   -1   124     pub last_level: usize,
   -1   125     pub next_level: usize,
   -1   126 
   -1   127 }
   -1   128 
  110   129 fn main() {
  111   130     let input = input::Input::new();
  112   131     let mut screen = term::Screen::new();
@@ -119,21 +138,23 @@ fn main() {
  119   138     let mut diamonds: Vec<Diamond> = vec![];
  120   139     let mut i_enemy = 0;
  121   140 
  122    -1     let mut player_x = 0.0;
  123    -1     let mut player_y = 0.0;
  124    -1     let mut player_dir = Dir::Stop;
  125    -1     let mut player_face = Dir::Right;
  126    -1     let mut player_speed = 30.0;
  127    -1     let player_size = 9.0;
  128    -1     let mut player_health = 50.0;
  129    -1     let mut player_health_max = 50.0;
  130    -1     let mut player_health_recover = 0.0;
  131    -1     let mut player_attack = 10.0;
  132    -1     let mut player_attack_radius = 30.0;
  133    -1     let mut player_xp = 0;
  134    -1     let mut player_last_level = 0;
  135    -1     let mut player_next_level = 10;
  136    -1     let mut player_diamond_radius = 15.0;
   -1   141     let mut player = Player {
   -1   142         x: 0.0,
   -1   143         y: 0.0,
   -1   144         dir: Dir::Stop,
   -1   145         face: Dir::Right,
   -1   146         speed: 30.0,
   -1   147         size: 9.0,
   -1   148         health: 50.0,
   -1   149         health_max: 50.0,
   -1   150         health_recover: 0.0,
   -1   151         power: 10.0,
   -1   152         damage_radius: 30.0,
   -1   153         diamond_radius: 15.0,
   -1   154         xp: 0,
   -1   155         last_level: 0,
   -1   156         next_level: 10,
   -1   157     };
  137   158 
  138   159     unsafe {
  139   160         libc::signal(libc::SIGINT, quit as usize);
@@ -146,33 +167,33 @@ fn main() {
  146   167         let dt = (time1 - time0).as_secs_f32();
  147   168 
  148   169         match input.getch() {
  149    -1             Some(b'w') => { player_dir = Dir::Up },
  150    -1             Some(b'A') => { player_dir = Dir::Up },
  151    -1             Some(b'a') => { player_dir = Dir::Left; player_face = Dir::Left },
  152    -1             Some(b'D') => { player_dir = Dir::Left; player_face = Dir::Left },
  153    -1             Some(b's') => { player_dir = Dir::Down },
  154    -1             Some(b'B') => { player_dir = Dir::Down },
  155    -1             Some(b'd') => { player_dir = Dir::Right; player_face = Dir::Right },
  156    -1             Some(b'C') => { player_dir = Dir::Right; player_face = Dir::Right },
  157    -1             Some(b' ') => { player_dir = Dir::Stop },
   -1   170             Some(b'w') => { player.dir = Dir::Up },
   -1   171             Some(b'A') => { player.dir = Dir::Up },
   -1   172             Some(b'a') => { player.dir = Dir::Left; player.face = Dir::Left },
   -1   173             Some(b'D') => { player.dir = Dir::Left; player.face = Dir::Left },
   -1   174             Some(b's') => { player.dir = Dir::Down },
   -1   175             Some(b'B') => { player.dir = Dir::Down },
   -1   176             Some(b'd') => { player.dir = Dir::Right; player.face = Dir::Right },
   -1   177             Some(b'C') => { player.dir = Dir::Right; player.face = Dir::Right },
   -1   178             Some(b' ') => { player.dir = Dir::Stop },
  158   179             Some(b'q') => { quit(0) },
  159   180             _ => {},
  160   181         }
  161   182 
  162   183         // move
  163    -1         match player_dir {
  164    -1             Dir::Up => { player_y -= player_speed * dt },
  165    -1             Dir::Right => { player_x += player_speed * dt },
  166    -1             Dir::Down => { player_y += player_speed * dt },
  167    -1             Dir::Left => { player_x -= player_speed * dt },
   -1   184         match player.dir {
   -1   185             Dir::Up => { player.y -= player.speed * dt },
   -1   186             Dir::Right => { player.x += player.speed * dt },
   -1   187             Dir::Down => { player.y += player.speed * dt },
   -1   188             Dir::Left => { player.x -= player.speed * dt },
  168   189             Dir::Stop => {},
  169   190         }
  170   191 
  171   192         for i in 0..enemies.len() {
  172   193             let enemy = &enemies[i];
  173   194 
  174    -1             let dxp = player_x - enemy.x;
  175    -1             let dyp = player_y - enemy.y;
   -1   195             let dxp = player.x - enemy.x;
   -1   196             let dyp = player.y - enemy.y;
  176   197             let dp = (dxp * dxp + dyp * dyp).sqrt();
  177   198 
  178   199             let mut dx = dxp / dp;
@@ -203,26 +224,26 @@ fn main() {
  203   224         }
  204   225 
  205   226         // recover
  206    -1         player_health = (player_health + player_health_recover * dt).min(player_health_max);
   -1   227         player.health = (player.health + player.health_recover * dt).min(player.health_max);
  207   228 
  208   229         // despawn
  209   230         enemies = enemies.into_iter().filter(|e| {
  210    -1             (e.y - player_y).abs() < height
  211    -1             && (e.x - player_x).abs() < width
   -1   231             (e.y - player.y).abs() < height
   -1   232             && (e.x - player.x).abs() < width
  212   233         }).collect();
  213   234 
  214   235         // interact with enemies
  215   236         for enemy in enemies.iter_mut() {
  216    -1             let dx = player_x - enemy.x;
  217    -1             let dy = player_y - enemy.y;
   -1   237             let dx = player.x - enemy.x;
   -1   238             let dy = player.y - enemy.y;
  218   239 
  219    -1             let size = enemy.t.size + player_size;
   -1   240             let size = enemy.t.size + player.size;
  220   241             if dx * dx + dy * 2.0 * dy * 2.0 < size * size {
  221    -1                 player_health -= enemy.t.power * dt;
   -1   242                 player.health -= enemy.t.power * dt;
  222   243             }
  223   244 
  224    -1             if dx * dx + dy * dy < player_attack_radius * player_attack_radius {
  225    -1                 enemy.health -= player_attack * dt;
   -1   245             if dx * dx + dy * dy < player.damage_radius * player.damage_radius {
   -1   246                 enemy.health -= player.power * dt;
  226   247             }
  227   248         }
  228   249 
@@ -238,36 +259,36 @@ fn main() {
  238   259             }
  239   260         }).collect();
  240   261 
  241    -1         if player_health < 0.0 {
  242    -1             println!("\nyou died (score: {})", player_xp);
   -1   262         if player.health < 0.0 {
   -1   263             println!("\nyou died (score: {})", player.xp);
  243   264             break;
  244   265         }
  245   266 
  246   267         // interact with diamonds
  247   268         diamonds = diamonds.into_iter().filter(|diamond| {
  248    -1             let dx = player_x - diamond.x;
  249    -1             let dy = player_y - diamond.y;
   -1   269             let dx = player.x - diamond.x;
   -1   270             let dy = player.y - diamond.y;
  250   271             let d = (dx * dx + dy * dy).sqrt();
  251    -1             if d < player_diamond_radius {
  252    -1                 player_xp += 1;
   -1   272             if d < player.diamond_radius {
   -1   273                 player.xp += 1;
  253   274                 return false;
  254   275             } else{
  255   276                 return true;
  256   277             }
  257   278         }).collect();
  258   279 
  259    -1         while player_xp >= player_next_level {
  260    -1             player_last_level = player_next_level;
  261    -1             player_next_level *= 2;
   -1   280         while player.xp >= player.next_level {
   -1   281             player.last_level = player.next_level;
   -1   282             player.next_level *= 2;
  262   283 
  263   284             match rng.gen_range(0, 7) {
  264    -1                 PERK_POWER => { player_attack *= 1.1; },
  265    -1                 PERK_HEALTH => { player_health_max *= 1.1; },
  266    -1                 PERK_SPEED => { player_speed *= 1.1; },
  267    -1                 PERK_RADIUS => { player_attack_radius *= 1.1; },
  268    -1                 PERK_HEAL => { player_health = player_health_max; },
  269    -1                 PERK_RECOVER => { player_health_recover += 0.2 },
  270    -1                 PERK_ATTRACT => { player_diamond_radius *= 1.1; },
   -1   285                 PERK_POWER => { player.power *= 1.1; },
   -1   286                 PERK_HEALTH => { player.health_max *= 1.1; },
   -1   287                 PERK_SPEED => { player.speed *= 1.1; },
   -1   288                 PERK_RADIUS => { player.damage_radius *= 1.1; },
   -1   289                 PERK_HEAL => { player.health = player.health_max; },
   -1   290                 PERK_RECOVER => { player.health_recover += 0.2 },
   -1   291                 PERK_ATTRACT => { player.diamond_radius *= 1.1; },
  271   292                 _ => unreachable!(),
  272   293             }
  273   294         }
@@ -295,8 +316,8 @@ fn main() {
  295   316             };
  296   317 
  297   318             enemies.push(enemies::get_enemy(
  298    -1                 spawn_x + player_x - width / 2.0,
  299    -1                 spawn_y + player_y - height / 2.0,
   -1   319                 spawn_x + player.x - width / 2.0,
   -1   320                 spawn_y + player.y - height / 2.0,
  300   321                 i_enemy,
  301   322             ));
  302   323             i_enemy += 1;
@@ -304,32 +325,33 @@ fn main() {
  304   325 
  305   326         // render
  306   327         clear(&mut screen);
  307    -1         circle(&mut screen, width / 2.0, height / 2.0, player_attack_radius, [0x00, 0xff, 0x00]);
   -1   328         circle(&mut screen, width / 2.0, height / 2.0, player.damage_radius, [0x00, 0xff, 0x00]);
  308   329 
  309   330         for diamond in diamonds.iter() {
  310    -1             let sx = diamond.x - player_x + width / 2.0;
  311    -1             let sy = diamond.y - player_y + height / 2.0;
   -1   331             let sx = diamond.x - player.x + width / 2.0;
   -1   332             let sy = diamond.y - player.y + height / 2.0;
  312   333             sprite(&mut screen, sx, sy, &sprites::DIAMOND, false);
  313   334         }
  314   335 
  315   336         enemies.sort_unstable_by_key(|e| e.y as i32);
  316    -1         for enemy in enemies.iter().filter(|e| e.y < player_y) {
  317    -1             let sx = enemy.x - player_x + width / 2.0;
  318    -1             let sy = enemy.y - player_y + height / 2.0;
  319    -1             sprite(&mut screen, sx, sy, enemy.t.sprite, enemy.x > player_x);
  320    -1         }
  321    -1 
  322    -1         sprite(&mut screen, width / 2.0, height / 2.0, &sprites::HERO, player_face == Dir::Left);
   -1   337         let mut player_rendered = false;
   -1   338         for enemy in enemies.iter() {
   -1   339             if !player_rendered && enemy.y > player.y {
   -1   340                 sprite(&mut screen, width / 2.0, height / 2.0, &sprites::HERO, player.face == Dir::Left);
   -1   341                 player_rendered = true;
   -1   342             }
  323   343 
  324    -1         for enemy in enemies.iter().filter(|e| e.y >= player_y) {
  325    -1             let sx = enemy.x - player_x + width / 2.0;
  326    -1             let sy = enemy.y - player_y + height / 2.0;
  327    -1             sprite(&mut screen, sx, sy, enemy.t.sprite, enemy.x > player_x);
   -1   344             let sx = enemy.x - player.x + width / 2.0;
   -1   345             let sy = enemy.y - player.y + height / 2.0;
   -1   346             sprite(&mut screen, sx, sy, enemy.t.sprite, enemy.x > player.x);
   -1   347         }
   -1   348         if !player_rendered {
   -1   349             sprite(&mut screen, width / 2.0, height / 2.0, &sprites::HERO, player.face == Dir::Left);
  328   350         }
  329   351 
  330    -1         bar(&mut screen, 0, (player_xp - player_last_level) as f32 / (player_next_level - player_last_level) as f32, [0x00, 0x00, 0xff]);
   -1   352         bar(&mut screen, 0, (player.xp - player.last_level) as f32 / (player.next_level - player.last_level) as f32, [0x00, 0x00, 0xff]);
  331   353         let h = screen.height;
  332    -1         bar(&mut screen, h - 3, player_health / player_health_max, [0xff, 0x00, 0x00]);
   -1   354         bar(&mut screen, h - 3, player.health / player.health_max, [0xff, 0x00, 0x00]);
  333   355 
  334   356         screen.render();
  335   357