Sprite doesn't render in Pong tutorial

#1

Hi everyone,
i’m trying to complete the Pong tutorial but i cannot render the paddles. Probably i’m making some mistakes. Can somebody help me?

This is my pong.rs file:

use amethyst::{
    assets::{AssetStorage, Loader, Handle},
    core::transform::Transform,
    ecs::prelude::{Component, DenseVecStorage},
    prelude::*,
    renderer::{Camera, ImageFormat, SpriteRender, SpriteSheet, SpriteSheetFormat, Texture},
};

pub const ARENA_WIDTH : f32 = 100.0;
pub const ARENA_HEIGHT : f32 = 100.0;


pub const PADDLE_HEIGHT : f32 = 16.0;
pub const PADDLE_WIDTH : f32 = 4.0;

pub struct Pong;

#[derive(PartialEq, Eq)]
pub enum Side{
	Left,
	Right,
}

pub struct Paddle{
	pub side : Side,
	pub width : f32,
	pub height : f32,
}

impl Paddle{
	fn new ( side : Side ) -> Paddle {
		Paddle {
			side,
			width : PADDLE_WIDTH,
			height : PADDLE_HEIGHT,
		}
	}
}

impl Component for Paddle{
	type Storage = DenseVecStorage<Self>;
}

impl SimpleState for Pong {
	fn on_start( &mut self, data : StateData<'_, GameData<'_,'_>>){
		let world = data.world;
		let sprite_sheet_handle = load_sprite_sheet(world);

		world.register::<Paddle>();

		initialise_paddles(world, sprite_sheet_handle);
		initialise_camera(world);

	}
}

fn initialise_camera( world : &mut World ){
	let mut transform = Transform::default();
	transform.set_translation_xyz( ARENA_WIDTH * 0.5, ARENA_HEIGHT * 0.5, 1.0);

	world
		.create_entity()
		.with(Camera::standard_2d(ARENA_WIDTH, ARENA_HEIGHT))
		.with(transform)
		.build();
}

fn initialise_paddles( world : &mut World, sprite_sheet : Handle<SpriteSheet> ){
	let mut left_transform  = Transform::default();
	let mut right_transform = Transform::default();

	let y = ARENA_HEIGHT * 0.5;

	let margin_from_border = PADDLE_WIDTH * 0.5;
	left_transform.set_translation_xyz( margin_from_border, y, 0.0 );
	right_transform.set_translation_xyz( ARENA_WIDTH - margin_from_border, y, 0.0 );

	let sprite_render = SpriteRender{
		sprite_sheet : sprite_sheet.clone(),
		sprite_number : 0,
	};

	world
		.create_entity()
		.with(sprite_render.clone())
		.with(Paddle::new(Side::Left))
		.with(left_transform)
		.build();

	world
		.create_entity()
		.with(Paddle::new(Side::Right))
		.with(right_transform)
		.with(sprite_render.clone())
		.build();

}

fn load_sprite_sheet( world : &mut World ) -> Handle<SpriteSheet> {

	let texture_handle = {
		let loader = world.read_resource::<Loader>();
		let texture_storage = world.read_resource::<AssetStorage<Texture>>();

		loader.load(
			"texture/pong_spritesheet.png",
			ImageFormat::default(),
			(),
			&texture_storage,
		)
	};

	let loader = world.read_resource::<Loader>();
	let sprite_sheet_store = world.read_resource::<AssetStorage<SpriteSheet>>();

	loader.load(
		"texture/pong_spritesheet.ron",
		SpriteSheetFormat(texture_handle),
		(),
		&sprite_sheet_store,
	)
}

and this is the main.rs

//! Pong Tutorial 1

use amethyst::{
    prelude::*,
    renderer::{
        plugins::{RenderFlat2D, RenderToWindow},
        types::DefaultBackend,
        RenderingBundle,
    },
    utils::application_root_dir,
};


mod pong;

use crate::pong::Pong;

use amethyst::core::transform::TransformBundle;

fn main() -> amethyst::Result<()>{

    amethyst::start_logger(Default::default());

    let app_root = application_root_dir()?;

    let display_config_path = app_root.join("config").join("display.ron");

    let game_data = GameDataBuilder::default()
        .with_bundle(
            RenderingBundle::<DefaultBackend>::new()
                .with_plugin(
                    RenderToWindow::from_config_path(display_config_path)
                        .with_clear([0.0, 0.0, 0.0, 1.0]),
                )
                .with_plugin(RenderFlat2D::default()),
        )?
        .with_bundle(TransformBundle::new())?;

    let asset_dir = app_root.join("assets");
    let world = World::new();
    let mut game = Application::new(asset_dir, Pong, game_data)?;

    game.run();

    Ok(())
}
#2

i don’t know how but now it’s working. Probably there was a typo…

2 Likes
(Kel) #3

It happens :laughing: let us know if you run into more problems!

2 Likes
(Sean Landis) #4

This is also happening to me on MacOS Catalina. Attempting to follow the tutorial, once I tried to render the paddles, I started receiving the following error and the paddles wouldn’t render. Directly copy/pasting the code from the example/pong_tutorial_2 causes the same error. I even cloned the Amethyst repo from github and ran cargo run --features=metal --example pong_tutorial_02, and still got the error:

[ERROR][amethyst_assets::storage] "renderer::SpriteSheet": Asset "texture/pong_spritesheet.ron" (handle id: Handle { id: 0 }) could not be loaded: Failed to load asset with name "texture/pong_spritesheet.ron"
[ERROR][amethyst_assets::progress] Error loading handle 0, renderer::SpriteSheet, with name texture/pong_spritesheet.ron: Failed to load asset with name "texture/pong_spritesheet.ron"
caused by: Failed to load asset with name "texture/pong_spritesheet.ron"
Error { inner: Inner { source: Some(Error { inner: Inner { source: Some(Error { inner: Inner { source: None, backtrace: None, error: LoadSpritesheetError(Parser(ExpectedIdentifier, Position { col: 1, line: 1 })) } }), backtrace: None, error: Format("SPRITE_SHEET") } }), backtrace: None, error: Asset("texture/pong_spritesheet.ron") } }
caused by: Format "SPRITE_SHEET" could not load asset
Error { inner: Inner { source: Some(Error { inner: Inner { source: None, backtrace: None, error: LoadSpritesheetError(Parser(ExpectedIdentifier, Position { col: 1, line: 1 })) } }), backtrace: None, error: Format("SPRITE_SHEET") } }
caused by: Failed to parse SpriteSheet
Error { inner: Inner { source: None, backtrace: None, error: LoadSpritesheetError(Parser(ExpectedIdentifier, Position { col: 1, line: 1 })) } }
[ERROR][amethyst_assets::progress] Note: to handle the error, use a `Progress` other than `()`
[WARN][amethyst_assets::storage] Loading unnecessary asset. Handle 6 is unique 
[ERROR][amethyst_assets::progress] Error loading handle 6, Mesh, with name texture/pong_spritesheet.png: Asset was loaded but no handle to it was saved.
caused by: Asset was loaded but no handle to it was saved.
Error { inner: Inner { source: None, backtrace: None, error: UnusedHandle } }
[ERROR][amethyst_assets::progress] Note: to handle the error, use a `Progress` other than `()`

However, this works fine on my Windows 10 machine.

1 Like
(Azriel Hoh) #5

Hiya @JiveSnake, recently on master there was a change in the sprites serialization format, and pong_tutorial_02 ron file was temporarily incorrect. It’s fixed on the latest master, so git pull should resolve the issue.

previously (incorrect)

Could you check if texture/pong_spritesheet.ron contains spritesheet_width and spritesheet_height?
In a previous version those were the field names, but they were updated to be texture_width and texture_height.

The other possibility is if you’re reading the book based off master (akin to “bleeding edge”), but using the published crate, or the other way round (reading the published book, but using amethyst master).

There is a difference in how the sprites are declared, best explained by this diff:

https://github.com/amethyst/amethyst/pull/2036/files#diff-9637c19325a50fb615bfd975cddba0fa

You’d want to add / remove the List(..) wrapper depending on which way you’re at.