Skip to content

Commit 415cfa8

Browse files
committed
v1.0.17
1 parent facc569 commit 415cfa8

25 files changed

+537
-168
lines changed

.github/workflows/deploy-ubuntu.yml

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Deploy
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*.*.*"
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
build-and-upload:
13+
14+
name: Build and upload
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Get the release version from the tag
21+
shell: bash
22+
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
23+
24+
- name: Install alsa.pc
25+
run: sudo apt-get install -y libasound2-dev
26+
27+
- name: Build
28+
run: cargo build --verbose --release
29+
30+
- name: Run tests
31+
run: cargo test --verbose
32+
33+
- name: Build archive
34+
shell: bash
35+
run: |
36+
binary_name="rebels"
37+
38+
dirname="$binary_name-${{ env.VERSION }}-x86_64-unknown-linux-gnu"
39+
mkdir "$dirname"
40+
mv "target/release/$binary_name" "$dirname"
41+
tar -czf "$dirname.tar.gz" "$dirname"
42+
echo "ASSET=$dirname.tar.gz" >> $GITHUB_ENV
43+
44+
- name: Release
45+
uses: softprops/action-gh-release@v2
46+
with:
47+
files: |
48+
${{ env.ASSET }}
49+
50+

.github/workflows/deploy.yml

-85
This file was deleted.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "rebels"
3-
version = "1.0.16"
3+
version = "1.0.17"
44
edition = "2021"
55

66
[profile.release]

assets/data/players_data.json

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"Giuseppe",
99
"Giampiero",
1010
"Carmelo",
11+
"Manolo",
1112
"Gianni",
1213
"Filippo",
1314
"Tancredi",
@@ -62,6 +63,7 @@
6263
],
6364
"last_names": [
6465
"Frittura",
66+
"Cipolla",
6567
"Cavour",
6668
"Rana",
6769
"Indovina",

src/image/types.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
use crate::{store::ASSETS_DIR, types::AppResult, ui::utils::img_to_lines};
12
use anyhow::anyhow;
23
use image::{ImageBuffer, Rgba};
34
use ratatui::text::Line;
45

5-
use crate::{store::ASSETS_DIR, types::AppResult, ui::utils::img_to_lines};
6-
7-
pub type Gif = Vec<ImageBuffer<Rgba<u8>, Vec<u8>>>;
6+
pub type GifFrame = ImageBuffer<Rgba<u8>, Vec<u8>>;
7+
pub type Gif = Vec<GifFrame>;
88
pub type FrameLines = Vec<Line<'static>>;
99
pub type GifLines = Vec<FrameLines>;
1010

src/image/utils.rs

+18-20
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,31 @@
11
use super::color_map::ColorMap;
2+
use super::types::GifFrame;
23
use crate::store::ASSETS_DIR;
34
use crate::types::AppResult;
45
use anyhow::anyhow;
56
use image::error::{ParameterError, ParameterErrorKind};
67
use image::ImageReader;
7-
use image::{ImageBuffer, ImageError, ImageResult, Rgba, RgbaImage};
8+
use image::{ImageError, ImageResult, Rgba, RgbaImage};
9+
use once_cell::sync::Lazy;
810
use std::io::Cursor;
911

12+
pub static UNIVERSE_BACKGROUND: Lazy<RgbaImage> =
13+
Lazy::new(|| read_image("planets/background.png").expect("Cannot open background.png."));
14+
pub static TRAVELLING_BACKGROUND: Lazy<RgbaImage> = Lazy::new(|| {
15+
read_image("planets/travelling_background.png").expect("Cannot open travelling_background.png.")
16+
});
17+
1018
pub trait ExtraImageUtils {
11-
fn copy_non_trasparent_from(
12-
&mut self,
13-
other: &ImageBuffer<Rgba<u8>, Vec<u8>>,
14-
x: u32,
15-
y: u32,
16-
) -> ImageResult<()>;
17-
fn apply_color_map(&mut self, color_map: ColorMap) -> &ImageBuffer<Rgba<u8>, Vec<u8>>;
19+
fn copy_non_trasparent_from(&mut self, other: &GifFrame, x: u32, y: u32) -> ImageResult<()>;
20+
fn apply_color_map(&mut self, color_map: ColorMap) -> &GifFrame;
1821
fn apply_color_map_with_shadow_mask(
1922
&mut self,
2023
color_map: ColorMap,
21-
mask: &ImageBuffer<Rgba<u8>, Vec<u8>>,
22-
) -> &ImageBuffer<Rgba<u8>, Vec<u8>>;
24+
mask: &GifFrame,
25+
) -> &GifFrame;
2326
}
2427

25-
impl ExtraImageUtils for ImageBuffer<Rgba<u8>, Vec<u8>> {
28+
impl ExtraImageUtils for GifFrame {
2629
/// Copies all non-transparent the pixels from another image into this image.
2730
///
2831
/// The other image is copied with the top-left corner of the
@@ -38,12 +41,7 @@ impl ExtraImageUtils for ImageBuffer<Rgba<u8>, Vec<u8>> {
3841
///
3942
/// [`GenericImageView::view`]: trait.GenericImageView.html#method.view
4043
/// [`FlatSamples`]: flat/struct.FlatSamples.html
41-
fn copy_non_trasparent_from(
42-
&mut self,
43-
other: &ImageBuffer<Rgba<u8>, Vec<u8>>,
44-
x: u32,
45-
y: u32,
46-
) -> ImageResult<()> {
44+
fn copy_non_trasparent_from(&mut self, other: &GifFrame, x: u32, y: u32) -> ImageResult<()> {
4745
// Do bounds checking here so we can use the non-bounds-checking
4846
// functions to copy pixels.
4947
if self.width() < other.width() + x || self.height() < other.height() + y {
@@ -62,7 +60,7 @@ impl ExtraImageUtils for ImageBuffer<Rgba<u8>, Vec<u8>> {
6260
}
6361
Ok(())
6462
}
65-
fn apply_color_map(&mut self, color_map: ColorMap) -> &ImageBuffer<Rgba<u8>, Vec<u8>> {
63+
fn apply_color_map(&mut self, color_map: ColorMap) -> &GifFrame {
6664
for k in 0..self.height() {
6765
for i in 0..self.width() {
6866
let p = self.get_pixel(i, k);
@@ -93,8 +91,8 @@ impl ExtraImageUtils for ImageBuffer<Rgba<u8>, Vec<u8>> {
9391
fn apply_color_map_with_shadow_mask(
9492
&mut self,
9593
color_map: ColorMap,
96-
mask: &ImageBuffer<Rgba<u8>, Vec<u8>>,
97-
) -> &ImageBuffer<Rgba<u8>, Vec<u8>> {
94+
mask: &GifFrame,
95+
) -> &GifFrame {
9896
for k in 0..self.height() {
9997
for i in 0..self.width() {
10098
let p = self.get_pixel(i, k);

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub mod event;
55
pub mod image;
66
pub mod network;
77
pub mod relayer;
8+
pub mod space_adventure;
89
pub mod ssh;
910
pub mod store;
1011
pub mod tui;

src/space_adventure/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub mod space;
2+
pub mod spaceship;
3+
pub mod traits;

src/space_adventure/space.rs

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
use super::{spaceship::SpaceshipEntity, traits::Entity};
2+
use crate::{
3+
image::{
4+
types::GifFrame,
5+
utils::{ExtraImageUtils, TRAVELLING_BACKGROUND},
6+
},
7+
types::{AppResult, Tick},
8+
world::{constants::SECONDS, spaceship::Spaceship},
9+
};
10+
use image::{GenericImageView, RgbaImage};
11+
use ratatui::layout::Rect;
12+
use std::collections::HashMap;
13+
14+
const FRICTION_COEFF: f64 = 0.05;
15+
const MAX_WIDTH: u32 = 160;
16+
const MAX_HEIGHT: u32 = 80;
17+
18+
#[derive(Default, Debug)]
19+
pub struct Space {
20+
id: usize,
21+
tick: usize,
22+
background: GifFrame,
23+
entities: HashMap<usize, Box<dyn Entity>>,
24+
}
25+
26+
impl Space {
27+
fn insert_entity(&mut self, entity: Box<dyn Entity>) -> usize {
28+
let id = self.id.clone();
29+
self.entities.insert(id, entity);
30+
self.id += 1;
31+
id
32+
}
33+
pub fn new() -> AppResult<Self> {
34+
let bg = TRAVELLING_BACKGROUND.clone();
35+
let mut background = RgbaImage::new(bg.width() * 2, bg.height() * 2);
36+
background.copy_non_trasparent_from(&bg, 0, 0)?;
37+
background.copy_non_trasparent_from(&bg, bg.width(), 0)?;
38+
background.copy_non_trasparent_from(&bg, 0, bg.height())?;
39+
background.copy_non_trasparent_from(&bg, bg.width(), bg.height())?;
40+
41+
Ok(Self {
42+
background,
43+
..Default::default()
44+
})
45+
}
46+
47+
pub fn with_spaceship(mut self, spaceship: &Spaceship) -> AppResult<Self> {
48+
let spaceship_entity = SpaceshipEntity::from_spaceship(spaceship)?;
49+
self.insert_entity(Box::new(spaceship_entity));
50+
Ok(self)
51+
}
52+
53+
pub fn current_id(&self) -> usize {
54+
self.id
55+
}
56+
57+
pub fn player(&self) -> &Box<dyn Entity> {
58+
self.entities
59+
.get(&0)
60+
.expect("There should be a player entity")
61+
}
62+
63+
pub fn player_mut(&mut self) -> &mut Box<dyn Entity> {
64+
self.entities
65+
.get_mut(&0)
66+
.expect("There should be a player entity")
67+
}
68+
69+
pub fn update(&mut self, deltatime_millis: Tick) -> AppResult<()> {
70+
self.tick += 1;
71+
let deltatime = deltatime_millis as f64 / SECONDS as f64;
72+
73+
for (_, entity) in self.entities.iter_mut() {
74+
let [x, y] = entity.position();
75+
let [vx, vy] = entity.velocity();
76+
let [mut ax, mut ay] = entity.accelleration();
77+
ax = ax - FRICTION_COEFF * vx;
78+
ay = ay - FRICTION_COEFF * vy;
79+
let new_velocity = [vx + ax * deltatime, vy + ay * deltatime];
80+
entity.set_velocity(new_velocity);
81+
entity.set_accelleration([0.0, 0.0]);
82+
83+
let [nvx, nvy] = entity.velocity();
84+
85+
let size = entity.size(self.tick);
86+
let new_position = [
87+
(x + nvx * deltatime).min((MAX_WIDTH - size[0]) as f64),
88+
(y + nvy * deltatime).min((MAX_HEIGHT - size[1]) as f64),
89+
];
90+
entity.set_position(new_position);
91+
}
92+
93+
Ok(())
94+
}
95+
96+
pub fn gif_frame(&self, frame_size: Rect) -> AppResult<GifFrame> {
97+
let mut base = self.background.clone();
98+
99+
for (_, entity) in self.entities.iter() {
100+
let [x, y] = entity.position();
101+
base.copy_non_trasparent_from(&entity.gif_frame(self.tick), x as u32, y as u32)?;
102+
}
103+
104+
let view = base.view(
105+
frame_size.x as u32,
106+
frame_size.y as u32,
107+
frame_size.width as u32,
108+
frame_size.height as u32 * 2, // Multiply by 2 because images are rendered in half the lines
109+
);
110+
111+
Ok(view.to_image())
112+
}
113+
}

0 commit comments

Comments
 (0)