added console

This commit is contained in:
dani 2023-07-02 20:16:18 +00:00
parent d264935ca3
commit a9ffc9bc6f
10 changed files with 163 additions and 13 deletions

BIN
examples/assets/hex2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 925 B

View File

@ -8,6 +8,7 @@ struct World {
img: Rc<Image>,
font: Rc<Tileset>,
pos: Vec2<i32>,
map: HexMap,
}
fn main() {
@ -22,11 +23,16 @@ impl Game for World {
img: Image::load_data(include_bytes!("assets/test.gif")),
font: Tileset::load_data(include_bytes!("assets/ega-8x14.gif"), Vec2 { x: 16, y: 16 }),
pos: Vec2::zero(),
map: HexMap::new(
Vec2 { x: 27, y: 13 },
Tileset::load_data(include_bytes!("assets/hex2.gif"), Vec2 { x: 1, y: 1 }),
),
}
}
fn update(&mut self, window_state: &mut WindowState) {
self.pos = window_state.mouse_pos();
window_state.log(format!("{}x{}", self.pos.x, self.pos.y).as_str());
}
fn on_event(&mut self, window_state: &mut WindowState, event: Event) {
@ -40,7 +46,8 @@ impl Game for World {
fn draw(&self, target: &mut Image) {
target.clear();
target.draw_image(Vec2 { x: 200, y: 100 }, &self.img);
target.draw_hexmap(Vec2 { x: 0, y: 0 }, &self.map);
/*target.draw_image(Vec2 { x: 200, y: 100 }, &self.img);
target.draw_image(self.pos, self.font.get(68));
target.draw_line(
@ -51,5 +58,7 @@ impl Game for World {
self.pos,
10,
);
*/
}
}

65
src/console.rs Normal file
View File

@ -0,0 +1,65 @@
use crate::{Image, Rect, Tileset, Vec2};
use std::collections::VecDeque;
pub(crate) struct Console {
lines: VecDeque<String>,
max_lines: usize,
max_line_length: usize,
}
impl Console {
pub(crate) fn new(max_lines: i32, max_line_length: i32) -> Self {
Self {
lines: VecDeque::new(),
max_lines: max_lines as usize,
max_line_length: max_line_length as usize,
}
}
pub(crate) fn add(&mut self, str: &str) {
if str.len() > self.max_line_length {
let (first, rest) = str.split_at(self.max_line_length);
self.add(first);
self.add(rest);
} else {
self.lines.push_back(str.into());
while self.lines.len() > self.max_lines {
self.lines.pop_front();
}
}
}
pub(crate) fn draw_to_image(&self, target: &mut Image, pos: Vec2<i32>, font: &Tileset) {
let height = self.max_lines as i32 * font.tile_size().y;
let width = self.max_line_length as i32 * font.tile_size().x;
target.fill_rect(
Rect {
pos,
size: Vec2 {
x: width,
y: height,
},
},
254,
);
let y = height + pos.y;
target.draw_line(
Vec2 { x: pos.x, y },
Vec2 {
x: pos.x + width,
y,
},
253,
);
for (i, str) in self.lines.iter().enumerate() {
target.draw_string(
pos + Vec2 {
x: 0,
y: i as i32 * font.tile_size().y,
},
str,
font,
);
}
}
}

BIN
src/ega-8x14.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -1,19 +1,20 @@
use crate::Vec2;
use crate::{Image, Tileset, Vec2};
use std::rc::Rc;
//odd-q vertical layout https://www.redblobgames.com/grids/hexagons
pub struct HexMap {
size: Vec2<i32>,
data: Vec<i32>,
tile_size: Vec2<i32>,
tileset: Rc<Tileset>,
}
impl HexMap {
//pub static
pub fn new(size: Vec2<i32>, tile_size: Vec2<i32>) -> Self {
pub fn new(size: Vec2<i32>, tileset: Rc<Tileset>) -> Self {
HexMap {
size,
data: vec![0; size.size()],
tile_size,
tileset,
}
}
@ -31,6 +32,22 @@ impl HexMap {
self.size
}
//pubcrate
pub(crate) fn draw_tile_to_image(
&self,
target: &mut Image,
coord: Vec2<i32>,
offset: Vec2<i32>,
) {
let x = coord.x * (self.tileset.tile_size().x as f64 * 3.0 / 4.0).ceil() as i32;
let y =
coord.y * self.tileset.tile_size().y + (coord.x % 2) * (self.tileset.tile_size().y / 2);
target.draw_image(
Vec2 { x, y } + offset,
self.tileset.get(self.data[self.coord_to_idx(coord)]),
)
}
//priv
fn coord_to_idx(&self, coord: Vec2<i32>) -> usize {
(coord.x + coord.y * self.size.x) as usize

View File

@ -1,5 +1,5 @@
use crate::vec2::Vec2;
use crate::{HexMap, Rect};
use crate::{HexMap, Rect, Tileset};
use std::fs;
use std::fs::File;
use std::rc::Rc;
@ -55,9 +55,13 @@ impl Image {
self.data.as_slice()
}
//pub fn draw_hexmap(&mut self, pos: Vec2<i32>, hexmap: &HexMap) {
// for pos in Vec2::zero()..pos {}
//}
pub fn draw_hexmap(&mut self, pos: Vec2<i32>, hexmap: &HexMap) {
for i in hexmap.size().to_rect().iter() {
if i.x % 1 == 0 {
hexmap.draw_tile_to_image(self, i, pos);
}
}
}
pub fn draw_image(&mut self, pos: Vec2<i32>, image: &Image) {
self.draw_image_partial(
@ -110,10 +114,30 @@ impl Image {
}
}
pub fn draw_string(&mut self, pos: Vec2<i32>, str: &str, font: &Tileset) {
assert!(str.is_ascii());
let array = str.as_bytes();
for i in 0..array.len() {
self.draw_image(
Vec2 {
x: pos.x + font.tile_size().x * i as i32,
y: pos.y,
},
font.get(array[i] as i32),
);
}
}
pub fn fill(&mut self, color: u8) {
self.data.fill(color);
}
pub fn fill_rect(&mut self, rect: Rect<i32>, color: u8) {
for pos in rect.iter() {
self.set_pixel(pos, color);
}
}
pub fn get_pixel(&self, pos: Vec2<i32>) -> u8 {
self.data[(pos.x + self.size.x * pos.y) as usize]
}

View File

@ -1,3 +1,4 @@
mod console;
mod hexmap;
mod image;
mod rect;
@ -5,6 +6,7 @@ mod tileset;
mod vec2;
mod window;
pub use console::*;
pub use hexmap::*;
pub use image::*;
pub use rect::*;

View File

@ -1,4 +1,5 @@
use crate::vec2::Vec2;
use crate::Vec2Iter;
use num::{Num, ToPrimitive};
#[derive(Copy, Clone)]
@ -19,6 +20,10 @@ impl<T: Num + Copy + ToPrimitive + PartialOrd> Rect<T> {
self.pos + self.size
}
pub fn iter(&self) -> Vec2Iter<T> {
self.pos.iter_to(self.size)
}
pub fn contains(&self, point: Vec2<T>) -> bool {
let p2 = self.pos2();
point.x >= self.pos.x && point.y >= self.pos.y && point.x < p2.x && point.y < p2.y

View File

@ -20,7 +20,7 @@ impl Tileset {
x: img.size().x / tile_count.x,
y: img.size().y / tile_count.y,
};
for tile in Vec2::zero().iter_to(tile_count) {
for tile in tile_count.to_rect().iter() {
let mut image = Image::new(size);
image.draw_image_partial(
Vec2::zero(),

View File

@ -1,11 +1,14 @@
use crate::console::Console;
use crate::image::Image;
use crate::vec2::Vec2;
use crate::Tileset;
use rand::Rng;
use std::cmp::{max, min};
use std::num::NonZeroU32;
use std::time::{Duration, Instant};
use winit::dpi::LogicalSize;
use winit::event::VirtualKeyCode::Escape;
use winit::event::ElementState::Pressed;
use winit::event::VirtualKeyCode::{Escape, F12};
use winit::event::{
ElementState, Event as WinitEvent, MouseButton as WinitMouseButton, WindowEvent,
};
@ -37,13 +40,21 @@ pub trait Game {
pub struct WindowState {
palette: [u32; 256],
mouse_pos: Vec2<i32>,
console: Console,
}
impl WindowState {
fn new() -> Self {
pub fn log(&mut self, msg: &str) {
self.console.add(msg);
}
}
impl WindowState {
fn new(console_size: Vec2<i32>) -> Self {
WindowState {
palette: [0u32; 256],
mouse_pos: Vec2::zero(),
console: Console::new(console_size.y, console_size.x),
}
}
pub fn set_palette(&mut self, index: u8, r: u8, g: u8, b: u8) {
@ -84,8 +95,15 @@ pub fn run<T: Game + 'static>(width: i32, height: i32) {
x: width,
y: height,
});
let mut window_state = WindowState::new();
let internal_font = Tileset::load_data(include_bytes!("ega-8x14.gif"), Vec2 { x: 16, y: 16 });
let mut window_state = WindowState::new(Vec2 {
x: width / internal_font.tile_size().x,
y: height / internal_font.tile_size().y / 3,
});
let mut game = T::new(&mut window_state);
window_state.console.add("Initialising Skunk2d");
let mut display_console = true;
let mut frames_since_last_second = 0;
let mut last_second = Instant::now();
@ -129,6 +147,9 @@ pub fn run<T: Game + 'static>(width: i32, height: i32) {
if k == Escape {
*control_flow = ControlFlow::Exit;
}
if k == F12 && input.state == Pressed {
display_console = !display_console;
}
};
}
WindowEvent::ModifiersChanged(_) => {}
@ -181,6 +202,13 @@ pub fn run<T: Game + 'static>(width: i32, height: i32) {
if Instant::now() - last_frame >= target_frame_duration {
game.update(&mut window_state);
game.draw(&mut screen);
if display_console {
window_state.console.draw_to_image(
&mut screen,
Vec2::zero(),
&internal_font,
);
}
let size = window.inner_size();
surface