Skip to content

adi_screen tutorial 3: Sprites

Jeron Aldaron Lau edited this page May 18, 2017 · 1 revision

Tutorial #3: Sprites

Ok. We've done the boring stuff. But, if you want to draw something interesting you need a sprite.

Use a context

Before we make sprites, we need to make a context. Our context will be a data structure that represents the program. Here's what it'll look like:

struct Context {
	window: Window,
	sprite: Sprite,
}

The struct keyword in Rust, defines a type that is made up of other variable types. This struct is made up of a Window and a Sprite. Elements in the struct are separated by commas. The last comma is optional.

Here's what the full code looks like, that uses a context and a sprite:

extern crate adi_screen;

use adi_screen::{ Window, Input, Sprite, Style };

struct Context {
	window: Window,
	sprite: Sprite,
}

fn redraw(context: &mut Context) {
	let disp2 = context.window.pulse_full_linear(2.0);

	context.window.background(disp2, disp2, disp2);
}

fn main() {
	let mut window = Window::create("project_name",
		include_bytes!("res/logo.ppm"), &[]);
	let sprite = Sprite::create(&mut window, &include!("res/sprite.data"),
		Style::create().gradient(), 1);

	let mut context = Context {
		sprite: sprite,
		window: window,
	};

	loop {
		match context.window.update() {
			Input::Back => break,
			Input::Redraw => redraw(&mut context),
			_ => {},
		}
	}
}

Copy the above code into a file. I will explain.

use adi_screen::{ Window, Input, Sprite, Style };

We've added Sprite and Style. A Sprite is an object that gets drawn on the screen. A Style is how that object is drawn.

struct Context {
	window: Window,
	sprite: Sprite,
}

fn redraw(context: &mut Context) {
	let disp2 = context.window.pulse_full_linear(2.0);

	context.window.background(disp2, disp2, disp2);
}

In order to access a variable within a struct, one must use a .. Example: context.window is accessing variable window within the struct context.

	let sprite = Sprite::create(&mut window, &include!("res/sprite.data"),
		Style::create().gradient(), 1);

Woah! There's a lot going on here. Like Window, Sprite and Style also implement a create() function. Sprite::create() has 4 parameters.

  • &mut Window - The window.
  • &[f32] - A reference to an array of vertices. O.K., but how do we do this? &include("res/sprite.data") - We're including an array from a file.
  • Style - The Style to use to draw the Sprite. Style::create().gradient() makes a gradient style. This is the most simple style.
  • The fourth parameter is the number of instances of the sprite to create.

Well, let's create that res/sprite.data file:

[

-1.0, -1.0, 0.0, 1.0,	1.0, 1.0, 0.0, 1.0,
1.0, 1.0, 0.0, 1.0,	0.0, 0.0, 1.0, 1.0,
1.0, -1.0, 0.0, 1.0,	0.0, 0.0, 1.0, 1.0,

1.0, 1.0, 0.0, 1.0,	0.0, 0.0, 1.0, 1.0,
-1.0, -1.0, 0.0, 1.0,	1.0, 1.0, 0.0, 1.0,
-1.0, 1.0, 0.0, 1.0,	1.0, 1.0, 0.0, 1.0,

]

It's broken up into 8 columns: X, Y, Z, W ( which should always be 1.0 ), R, G, B, A

The rows are split into groups of 3. Each group of 3 rows is a triangle. 2 triangles make a rectangle.

	let mut context = Context {
		sprite: sprite,
		window: window,
	};

	loop {
		match context.window.update() {
			Input::Back => break,
			Input::Redraw => redraw(&mut context),
			_ => {},
		}
	}

Finally, the context is created. Since we're not using references to define the context, the variables sprite and window move inside the context. That means you can't just say window anymore - you now have to say context.window. You can see this inside the loop.

Try cargo run, and see what happens.