gdritter repos wenaglia / 3435b15
some tileset changes and some preliminary collision code Getty Ritter 5 years ago
10 changed file(s) with 188 addition(s) and 121 deletion(s). Collapse all Expand all
11 <?xml version="1.0" encoding="UTF-8"?>
2 <tileset name="animaltransiro" tilewidth="24" tileheight="24" tilecount="1024" columns="32">
3 <image source="../tiles/spritesheet.png" width="768" height="768"/>
2 <tileset version="1.2" tiledversion="1.2.3" name="animaltransiro" tilewidth="24" tileheight="24" tilecount="1024" columns="32">
3 <image source="spritesheet.png" width="768" height="768"/>
44 <terraintypes>
55 <terrain name="Grass" tile="0"/>
66 <terrain name="Dirt" tile="70"/>
11 <?xml version="1.0" encoding="UTF-8"?>
2 <map version="1.0.0" orientation="orthogonal" renderorder="right-down" width="16" height="12" tilewidth="24" tileheight="24" nextobjectid="10">
2 <map version="1.2" tiledversion="1.2.3" orientation="orthogonal" renderorder="right-down" width="16" height="12" tilewidth="24" tileheight="24" infinite="0" nextlayerid="5" nextobjectid="10">
33 <properties>
44 <property name="south" value="south"/>
55 <property name="west" value="west"/>
66 </properties>
77 <tileset firstgid="1" source="animaltransiro.tsx"/>
8 <layer name="tiles" width="16" height="12">
8 <layer id="1" name="tiles" width="16" height="12">
99 <data encoding="csv">
1010 1,1,1,1,1,1,33,1,1,1,1,1,33,1,1,1,
1111 1,1,1,1,1,43,45,1,1,1,1,1,1,43,44,45,
1515 44,79,77,1,1,1,75,76,77,1,70,73,40,75,77,1,
1616 76,76,78,45,1,33,107,108,109,1,70,71,72,107,109,1,
1717 76,76,46,109,1,1,38,39,39,39,74,71,72,33,1,1,
18 108,108,109,1,1,38,74,41,103,42,71,41,104,1,1,1,
19 1,1,1,1,38,74,71,72,38,74,41,104,1,1,33,1,
20 1,1,33,1,102,103,42,73,74,41,104,1,1,1,1,1,
18 108,108,109,1,1,38,74,103,42,71,71,41,104,1,1,1,
19 1,1,1,1,38,74,72,1,70,71,41,104,1,1,33,1,
20 1,1,33,1,102,103,73,39,74,41,104,1,1,1,1,1,
2121 1,1,1,1,1,1,70,71,71,72,1,1,1,1,1,1
2222 </data>
2323 </layer>
24 <layer name="entities" width="16" height="12">
24 <layer id="2" name="entities" width="16" height="12">
2525 <data encoding="csv">
2626 0,26,27,28,29,0,0,0,30,31,32,0,0,0,0,0,
2727 0,58,59,60,61,0,0,37,62,63,64,0,0,0,0,0,
3737 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3838 </data>
3939 </layer>
40 <layer name="decoration" width="16" height="12">
40 <layer id="3" name="decoration" width="16" height="12">
4141 <data encoding="csv">
4242 0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,
4343 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
5353 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5454 </data>
5555 </layer>
56 <objectgroup name="meta">
56 <objectgroup id="4" name="meta">
5757 <object id="2" x="96" y="72" width="24" height="24">
5858 <properties>
5959 <property name="signText" value="Bonvenon al la kafejo!"/>
Binary diff not shown
1 use specs::{Component, VecStorage, NullStorage};
2
3 /// Register all the components with the world.
4 pub fn register(world: &mut specs::World) {
5 world.register::<Position>();
6 world.register::<Velocity>();
7 world.register::<Sprite>();
8 world.register::<Background>();
9 world.register::<Foreground>();
10 world.register::<Decoration>();
11 world.register::<Controlled>();
12 world.register::<Collision>();
13 world.register::<Blocking>();
14 }
15
16 /// The `Position` component represents (in world coordinates) a thing
17 /// that has a position in the world, measured from the top-left of
18 /// the thing.
19 #[derive(Component, Debug)]
20 #[storage(VecStorage)]
21 pub struct Position {
22 pub x: f32,
23 pub y: f32,
24 }
25
26 impl Position {
27 /// Convert a `Position` to a screen point
28 pub fn to_point(&self) -> ggez::nalgebra::Point2<f32> {
29 ggez::nalgebra::Point2::new(self.x * 3.0, self.y * 3.0)
30 }
31
32 pub fn to_grid(&self) -> (i32, i32) {
33 ((self.x / 24.0) as i32,
34 (self.y / 24.0) as i32,
35 )
36 }
37
38 pub fn moved(&self, vel: &Velocity) -> Position {
39 Position {
40 x: self.x + vel.dx,
41 y: self.x + vel.dy,
42 }
43 }
44 }
45
46 /// The `Velocity` componenent is present on any entity that moves
47 /// through the world, and represents its rate of change per
48 /// time-unit.
49 #[derive(Component, Debug)]
50 #[storage(VecStorage)]
51 pub struct Velocity {
52 pub dx: f32,
53 pub dy: f32,
54 }
55
56
57 /// The `Sprite` components represents the current display location of
58 /// a sprite in the spritesheet.
59 #[derive(Component, Debug)]
60 #[storage(VecStorage)]
61 pub struct Sprite {
62 pub u: u8,
63 pub v: u8,
64 }
65
66 impl Sprite {
67 /// Convert a `Sprite` into the rectangle that specifies the
68 /// sprite location on the spritesheet
69 pub fn to_rect(&self) -> ggez::graphics::Rect {
70 ggez::graphics::Rect {
71 x: (1.0 / 32.0) * self.u as f32,
72 y: (1.0 / 32.0) * self.v as f32,
73 w: 1.0 / 32.0,
74 h: 1.0 / 32.0,
75 }
76 }
77 }
78
79 /// A drawing-phase component: represents tiles that appear in the
80 /// background of everything.
81 #[derive(Component, Default, Debug)]
82 #[storage(NullStorage)]
83 pub struct Background;
84
85 /// A drawing-phase component: represents tiles which appear in the
86 /// foreground, possibly entities.
87 #[derive(Component, Default, Debug)]
88 #[storage(NullStorage)]
89 pub struct Foreground;
90
91 /// A drawing-phase component: represents tiles which appear on top of
92 /// everything else, such as the tops of trees or roofs of houses.
93 #[derive(Component, Default, Debug)]
94 #[storage(NullStorage)]
95 pub struct Decoration;
96
97 /// A component that represents entities which are controlled by the
98 /// keyboard.
99 #[derive(Component, Default, Debug)]
100 #[storage(NullStorage)]
101 pub struct Controlled;
102
103 /// A component that represents entities which can collide with other
104 /// things.
105 #[derive(Component, Debug)]
106 #[storage(VecStorage)]
107 pub struct Collision {
108 pub has_collision: bool
109 }
110
111 #[derive(Component, Default, Debug)]
112 #[storage(NullStorage)]
113 pub struct Blocking;
+0
-94
src/components.rs less more
1 use specs::{Component, VecStorage, NullStorage};
2
3 /// Register all the components with the world.
4 pub fn register(world: &mut specs::World) {
5 world.register::<Position>();
6 world.register::<Velocity>();
7 world.register::<Sprite>();
8 world.register::<Background>();
9 world.register::<Foreground>();
10 world.register::<Decoration>();
11 world.register::<Controlled>();
12 }
13
14 /// The `Position` component represents (in world coordinates) a thing
15 /// that has a position in the world, measured from the top-left of
16 /// the thing.
17 #[derive(Component, Debug)]
18 #[storage(VecStorage)]
19 pub struct Position {
20 pub x: f32,
21 pub y: f32,
22 }
23
24 impl Position {
25 /// Convert a `Position` to a screen point
26 pub fn to_point(&self) -> ggez::nalgebra::Point2<f32> {
27 ggez::nalgebra::Point2::new(self.x * 3.0, self.y * 3.0)
28 }
29 }
30
31 /// The `Velocity` componenent is present on any entity that moves
32 /// through the world, and represents its rate of change per
33 /// time-unit.
34 #[derive(Component, Debug)]
35 #[storage(VecStorage)]
36 pub struct Velocity {
37 pub dx: f32,
38 pub dy: f32,
39 }
40
41
42 /// The `Sprite` components represents the current display location of
43 /// a sprite in the spritesheet.
44 #[derive(Component, Debug)]
45 #[storage(VecStorage)]
46 pub struct Sprite {
47 pub u: u8,
48 pub v: u8,
49 }
50
51 impl Sprite {
52 /// Convert a `Sprite` into the rectangle that specifies the
53 /// sprite location on the spritesheet
54 pub fn to_rect(&self) -> ggez::graphics::Rect {
55 ggez::graphics::Rect {
56 x: (1.0 / 32.0) * self.u as f32,
57 y: (1.0 / 32.0) * self.v as f32,
58 w: 1.0 / 32.0,
59 h: 1.0 / 32.0,
60 }
61 }
62 }
63
64 /// A drawing-phase component: represents tiles that appear in the
65 /// background of everything.
66 #[derive(Component, Default, Debug)]
67 #[storage(NullStorage)]
68 pub struct Background;
69
70 /// A drawing-phase component: represents tiles which appear in the
71 /// foreground, possibly entities.
72 #[derive(Component, Default, Debug)]
73 #[storage(NullStorage)]
74 pub struct Foreground;
75
76 /// A drawing-phase component: represents tiles which appear on top of
77 /// everything else, such as the tops of trees or roofs of houses.
78 #[derive(Component, Default, Debug)]
79 #[storage(NullStorage)]
80 pub struct Decoration;
81
82 /// A component that represents entities which are controlled by the
83 /// keyboard.
84 #[derive(Component, Default, Debug)]
85 #[storage(NullStorage)]
86 pub struct Controlled;
87
88 /// A component that represents entities which can collide with other
89 /// things.
90 #[derive(Component, Debug)]
91 #[storage(VecStorage)]
92 pub struct Collision {
93 pub has_collision: bool
94 }
1010 use sdl2::keyboard as sdl;
1111
1212 pub mod consts;
13 pub mod components;
13 pub mod com;
1414 pub mod game;
1515 pub mod res;
1616 pub mod sys;
1818 use game::MyGame;
1919
2020 impl EventHandler for MyGame {
21
2221 fn update(&mut self, _ctx: &mut Context) -> GameResult<()> {
2322 sys::input::systems(self);
2423 sys::physics::systems(self);
5554
5655 fn main() -> Result<(), ggez::error::GameError> {
5756 let mut world = specs::World::new();
58 components::register(&mut world);
57 com::register(&mut world);
5958
6059 res::world_from_file(&mut world, "assets/main.tmx");
6160
11 use crate::consts;
2 use crate::components::*;
2 use crate::com::*;
33
44 use specs::world::Builder;
55 use std::path::Path;
4747 pub fn world_from_file<P: AsRef<Path>>(w: &mut specs::World, path: P) {
4848 let tiled::Map {
4949 layers,
50 tilesets,
5051 ..
5152 } = tiled::parse_file(path.as_ref()).unwrap();
5253
6667 DrawLayer::Foreground => e.with(Foreground),
6768 DrawLayer::Decoration => e.with(Decoration),
6869 };
70
71 let e = if tilesets[0].tiles[n as usize].properties["pass"] ==
72 tiled::PropertyValue::BoolValue(false) {
73 e.with(Blocking)
74 } else {
75 e
76 };
6977 e.build();
7078 }
7179 }
8290 .with(Velocity { dx: 0.0, dy: 0.0 })
8391 .with(Foreground)
8492 .with(Controlled)
93 .with(Collision { has_collision: false })
8594 .build();
8695 }
11 use crate::consts;
2 use crate::components::{self,Position,Sprite};
2 use crate::com::{self,Position,Sprite};
33 use crate::game::MyGame;
44
55 use ggez::{
5353
5454 Draw {
5555 ctx,
56 _phase: components::Background,
56 _phase: com::Background,
5757 }.run_now(&game.world.res);
5858 Draw {
5959 ctx,
60 _phase: components::Foreground,
60 _phase: com::Foreground,
6161 }.run_now(&game.world.res);
6262 Draw {
6363 ctx,
64 _phase: components::Decoration,
64 _phase: com::Decoration,
6565 }.run_now(&game.world.res);
6666
6767 graphics::present(ctx);
1 use crate::components::{Controlled, Velocity};
1 use crate::com::{Controlled, Velocity};
22 use crate::game::MyGame;
33 use crate::res::KeySet;
44
1 use crate::components::{Velocity, Position};
1 use crate::com::{Blocking, Collision, Velocity, Position};
22 use crate::game::MyGame;
33
4 use specs::RunNow;
4 use specs::{Join,RunNow};
5
6 struct Intersection;
7
8 impl<'a> specs::System<'a> for Intersection {
9 type SystemData = (
10 specs::Entities<'a>,
11 specs::ReadStorage<'a, Position>,
12 specs::ReadStorage<'a, Velocity>,
13 specs::ReadStorage<'a, Blocking>,
14 specs::WriteStorage<'a, Collision>,
15 );
16
17 fn run(&mut self, (entity, position, velocity, blocking, mut collision): Self::SystemData) {
18 let mut spacemap = std::collections::HashMap::new();
19 for (e, pos, _) in (&entity, &position, &blocking).join() {
20 spacemap.insert(pos.to_grid(), e);
21 }
22
23 for (pos, vel, col) in (&position, &velocity, &mut collision).join() {
24 if let Some(_) = spacemap.get(&pos.moved(vel).to_grid()) {
25 col.has_collision = true;
26 }
27 }
28 }
29 }
530
631 struct Physics;
732
833 impl <'a> specs::System<'a> for Physics {
934 type SystemData = (
1035 specs::ReadStorage<'a, Velocity>,
36 specs::ReadStorage<'a, Collision>,
1137 specs::WriteStorage<'a, Position>,
1238 );
1339
14 fn run(&mut self, (velocity, mut position): Self::SystemData) {
15 use specs::Join;
16
17 for (vel, pos) in (&velocity, &mut position).join() {
18 pos.x += vel.dx;
19 pos.y += vel.dy;
40 fn run(&mut self, (velocity, collision, mut position): Self::SystemData) {
41 for (vel, col, pos) in (&velocity, &collision, &mut position).join() {
42 if !col.has_collision {
43 pos.x += vel.dx;
44 pos.y += vel.dy;
45 }
2046 }
2147 }
2248 }
2349
50 struct ResetCollision;
51
52 impl<'a> specs::System<'a> for ResetCollision {
53 type SystemData =
54 specs::WriteStorage<'a, Collision>;
55
56 fn run(&mut self, mut collision: Self::SystemData) {
57 for mut e in (&mut collision).join() {
58 e.has_collision = false;
59 }
60 }
61 }
2462
2563 pub fn systems(game: &mut MyGame) {
64 Intersection.run_now(&game.world.res);
2665 Physics.run_now(&game.world.res);
66 ResetCollision.run_now(&game.world.res);
2767 }