|
| 1 | +use amethyst::{ |
| 2 | + assets::{AssetStorage, Loader, Handle}, |
| 3 | + core::transform::Transform, |
| 4 | + ecs::prelude::{Component, DenseVecStorage}, |
| 5 | + prelude::*, |
| 6 | + renderer::{Camera, ImageFormat, SpriteRender, SpriteSheet, SpriteSheetFormat, Texture}, |
| 7 | +}; |
| 8 | + |
| 9 | +pub struct PongGame; |
| 10 | + |
| 11 | +const IDENTITY: f32 = 1.0; |
| 12 | +const Z_FRONT: f32 = 0.0; |
| 13 | + |
| 14 | +const ARENA_WIDTH: f32 = 100.0; |
| 15 | +const ARENA_HEIGHT: f32 = 100.0; |
| 16 | +const HALVE_WIDTH: f32 = ARENA_WIDTH * 0.5; |
| 17 | +const HALVE_HEIGHT: f32 = ARENA_HEIGHT * 0.5; |
| 18 | + |
| 19 | +const PADDLE_WIDTH: f32 = 4.0; |
| 20 | +const PADDLE_HEIGHT: f32 = 16.0; |
| 21 | + |
| 22 | +const PADDLE_PIVOT_X: f32 = PADDLE_WIDTH * 0.5; |
| 23 | +const PADDLE_LEFT_X: f32 = PADDLE_PIVOT_X; |
| 24 | +const PADDLE_RIGHT_X: f32 = ARENA_WIDTH - PADDLE_PIVOT_X; |
| 25 | +const PADDLE_INITIAL_Y: f32 = HALVE_HEIGHT; |
| 26 | +const PADDLE_Z: f32 = Z_FRONT; |
| 27 | +const PADDLE_SPRITE_NUM: usize = 0; |
| 28 | + |
| 29 | +const GAME_SPRITE_SHEET_TEXTURE: &str = "texture/pong_spritesheet.png"; |
| 30 | +const GAME_SPRITE_SHEET_RON: &str = "texture/pong_spritesheet.ron"; |
| 31 | + |
| 32 | +fn initialise_camera(world: &mut World) { |
| 33 | + // Setup camera in a way that our screen covers whole arena and (0, 0) is in the bottom left. |
| 34 | + let mut transform = Transform::default(); |
| 35 | + transform.set_translation_xyz(HALVE_WIDTH, HALVE_HEIGHT, IDENTITY); |
| 36 | + |
| 37 | + world |
| 38 | + .create_entity() |
| 39 | + .with(Camera::standard_2d(ARENA_WIDTH, ARENA_HEIGHT)) |
| 40 | + .with(transform) |
| 41 | + .build(); |
| 42 | +} |
| 43 | + |
| 44 | +#[derive(PartialEq, Eq)] |
| 45 | +pub enum Side { |
| 46 | + Left, |
| 47 | + Right, |
| 48 | +} |
| 49 | + |
| 50 | +pub struct Paddle { |
| 51 | + pub side: Side, |
| 52 | + pub width: f32, |
| 53 | + pub height: f32, |
| 54 | +} |
| 55 | + |
| 56 | +impl Paddle { |
| 57 | + fn new(side: Side) -> Paddle { |
| 58 | + Paddle { |
| 59 | + side, |
| 60 | + width: PADDLE_WIDTH, |
| 61 | + height: PADDLE_HEIGHT, |
| 62 | + } |
| 63 | + } |
| 64 | +} |
| 65 | + |
| 66 | +impl Component for Paddle { |
| 67 | + type Storage = DenseVecStorage<Self>; |
| 68 | +} |
| 69 | + |
| 70 | +/// Initialises one paddle on the left, and one paddle on the right. |
| 71 | +fn initialise_paddles(world: &mut World, sprite_sheet_handle: Handle<SpriteSheet>) { |
| 72 | + let mut left_transform = Transform::default(); |
| 73 | + let mut right_transform = Transform::default(); |
| 74 | + |
| 75 | + // Correctly position the paddles. |
| 76 | + left_transform.set_translation_xyz(PADDLE_LEFT_X, PADDLE_INITIAL_Y, PADDLE_Z); |
| 77 | + right_transform.set_translation_xyz(PADDLE_RIGHT_X, PADDLE_INITIAL_Y, PADDLE_Z); |
| 78 | + |
| 79 | + // Assign the sprites for the paddles |
| 80 | + let sprite_render = SpriteRender { |
| 81 | + sprite_sheet: sprite_sheet_handle, |
| 82 | + sprite_number: PADDLE_SPRITE_NUM, |
| 83 | + }; |
| 84 | + |
| 85 | + // Create a left plank entity. |
| 86 | + world |
| 87 | + .create_entity() |
| 88 | + .with(sprite_render.clone()) |
| 89 | + .with(Paddle::new(Side::Left)) |
| 90 | + .with(left_transform) |
| 91 | + .build(); |
| 92 | + |
| 93 | + // Create right plank entity. |
| 94 | + world |
| 95 | + .create_entity() |
| 96 | + .with(sprite_render) |
| 97 | + .with(Paddle::new(Side::Right)) |
| 98 | + .with(right_transform) |
| 99 | + .build(); |
| 100 | +} |
| 101 | + |
| 102 | +fn load_sprite_sheet(world: &mut World) -> Handle<SpriteSheet> { |
| 103 | + let loader = world.read_resource::<Loader>(); |
| 104 | + |
| 105 | + // The texture is the pixel data |
| 106 | + // `texture_handle` is a cloneable reference to the texture |
| 107 | + let texture_handle = { |
| 108 | + let texture_storage = world.read_resource::<AssetStorage<Texture>>(); |
| 109 | + loader.load( |
| 110 | + GAME_SPRITE_SHEET_TEXTURE, |
| 111 | + ImageFormat::default(), |
| 112 | + (), |
| 113 | + &texture_storage, |
| 114 | + ) |
| 115 | + }; |
| 116 | + |
| 117 | + // Load the sprite sheet necessary to render the graphics. |
| 118 | + let sprite_sheet_handle = { |
| 119 | + let sprite_sheet_store = world.read_resource::<AssetStorage<SpriteSheet>>(); |
| 120 | + loader.load( |
| 121 | + GAME_SPRITE_SHEET_RON, // Here we load the associated ron file |
| 122 | + SpriteSheetFormat(texture_handle), |
| 123 | + (), |
| 124 | + &sprite_sheet_store, |
| 125 | + ) |
| 126 | + }; |
| 127 | + |
| 128 | + sprite_sheet_handle |
| 129 | +} |
| 130 | + |
| 131 | +impl SimpleState for PongGame { |
| 132 | + fn on_start(&mut self, data: StateData<'_, GameData<'_, '_>>) { |
| 133 | + let world = data.world; |
| 134 | + |
| 135 | + // Load the spritesheet necessary to render the graphics. |
| 136 | + let sprite_sheet_handle = load_sprite_sheet(world); |
| 137 | + |
| 138 | + world.register::<Paddle>(); |
| 139 | + |
| 140 | + initialise_paddles(world, sprite_sheet_handle); |
| 141 | + initialise_camera(world); |
| 142 | + } |
| 143 | +} |
0 commit comments