Update public API to provide &mut [u8]
instead of accepting &[u8]
from the app (#22)
- Closes #19
This commit is contained in:
parent
b18690f19f
commit
8801bad58a
|
@ -42,7 +42,7 @@ fn main() -> Result<(), Error> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let surface_texture = SurfaceTexture::new(width, height, surface);
|
let surface_texture = SurfaceTexture::new(width, height, surface);
|
||||||
let mut pixels = Pixels::new(224, 256, surface_texture)?;
|
let mut pixels = Pixels::new(SCREEN_WIDTH as u32, SCREEN_HEIGHT as u32, surface_texture)?;
|
||||||
let mut invaders = World::new(debug);
|
let mut invaders = World::new(debug);
|
||||||
let mut time = Instant::now();
|
let mut time = Instant::now();
|
||||||
let mut controls = Controls::default();
|
let mut controls = Controls::default();
|
||||||
|
@ -54,7 +54,8 @@ fn main() -> Result<(), Error> {
|
||||||
event: WindowEvent::RedrawRequested,
|
event: WindowEvent::RedrawRequested,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
pixels.render(invaders.draw());
|
invaders.draw(pixels.get_frame());
|
||||||
|
pixels.render();
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,6 @@ pub struct World {
|
||||||
collision: Collision,
|
collision: Collision,
|
||||||
score: u32,
|
score: u32,
|
||||||
assets: Assets,
|
assets: Assets,
|
||||||
screen: Vec<u8>,
|
|
||||||
dt: Duration,
|
dt: Duration,
|
||||||
gameover: bool,
|
gameover: bool,
|
||||||
random: OsRng,
|
random: OsRng,
|
||||||
|
@ -149,10 +148,6 @@ impl World {
|
||||||
let collision = Collision::default();
|
let collision = Collision::default();
|
||||||
let score = 0;
|
let score = 0;
|
||||||
|
|
||||||
// Create a screen with the correct size
|
|
||||||
let mut screen = Vec::new();
|
|
||||||
screen.resize_with(SCREEN_WIDTH * SCREEN_HEIGHT * 4, Default::default);
|
|
||||||
|
|
||||||
let dt = Duration::default();
|
let dt = Duration::default();
|
||||||
let gameover = false;
|
let gameover = false;
|
||||||
let random = OsRng;
|
let random = OsRng;
|
||||||
|
@ -166,7 +161,6 @@ impl World {
|
||||||
collision,
|
collision,
|
||||||
score,
|
score,
|
||||||
assets,
|
assets,
|
||||||
screen,
|
|
||||||
dt,
|
dt,
|
||||||
gameover,
|
gameover,
|
||||||
random,
|
random,
|
||||||
|
@ -261,47 +255,45 @@ impl World {
|
||||||
/// Draw the internal state to the screen.
|
/// Draw the internal state to the screen.
|
||||||
///
|
///
|
||||||
/// Calling this method more than once without an `update` call between is a no-op.
|
/// Calling this method more than once without an `update` call between is a no-op.
|
||||||
pub fn draw(&mut self) -> &[u8] {
|
pub fn draw(&mut self, screen: &mut [u8]) {
|
||||||
// Clear the screen
|
// Clear the screen
|
||||||
self.clear();
|
clear(screen);
|
||||||
|
|
||||||
// Draw the invaders
|
// Draw the invaders
|
||||||
for row in &self.invaders.grid {
|
for row in &self.invaders.grid {
|
||||||
for col in row {
|
for col in row {
|
||||||
if let Some(invader) = col {
|
if let Some(invader) = col {
|
||||||
blit(&mut self.screen, &invader.pos, &invader.sprite);
|
blit(screen, &invader.pos, &invader.sprite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the shields
|
// Draw the shields
|
||||||
for shield in &self.shields {
|
for shield in &self.shields {
|
||||||
blit(&mut self.screen, &shield.pos, &shield.sprite);
|
blit(screen, &shield.pos, &shield.sprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the player
|
// Draw the player
|
||||||
blit(&mut self.screen, &self.player.pos, &self.player.sprite);
|
blit(screen, &self.player.pos, &self.player.sprite);
|
||||||
|
|
||||||
// Draw the bullet
|
// Draw the bullet
|
||||||
if let Some(bullet) = &self.bullet {
|
if let Some(bullet) = &self.bullet {
|
||||||
blit(&mut self.screen, &bullet.pos, &bullet.sprite);
|
blit(screen, &bullet.pos, &bullet.sprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw lasers
|
// Draw lasers
|
||||||
for laser in self.lasers.iter() {
|
for laser in self.lasers.iter() {
|
||||||
blit(&mut self.screen, &laser.pos, &laser.sprite);
|
blit(screen, &laser.pos, &laser.sprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw debug information
|
// Draw debug information
|
||||||
if self.debug {
|
if self.debug {
|
||||||
debug::draw_invaders(&mut self.screen, &self.invaders, &self.collision);
|
debug::draw_invaders(screen, &self.invaders, &self.collision);
|
||||||
debug::draw_bullet(&mut self.screen, self.bullet.as_ref());
|
debug::draw_bullet(screen, self.bullet.as_ref());
|
||||||
debug::draw_lasers(&mut self.screen, &self.lasers);
|
debug::draw_lasers(screen, &self.lasers);
|
||||||
debug::draw_player(&mut self.screen, &self.player, &self.collision);
|
debug::draw_player(screen, &self.player, &self.collision);
|
||||||
debug::draw_shields(&mut self.screen, &self.shields, &self.collision);
|
debug::draw_shields(screen, &self.shields, &self.collision);
|
||||||
}
|
}
|
||||||
|
|
||||||
&self.screen
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step_invaders(&mut self) {
|
fn step_invaders(&mut self) {
|
||||||
|
@ -406,13 +398,6 @@ impl World {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear the screen
|
|
||||||
fn clear(&mut self) {
|
|
||||||
for (i, byte) in self.screen.iter_mut().enumerate() {
|
|
||||||
*byte = if i % 4 == 3 { 255 } else { 0 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for World {
|
impl Default for World {
|
||||||
|
@ -522,6 +507,13 @@ impl Default for Bounds {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clear the screen
|
||||||
|
fn clear(screen: &mut [u8]) {
|
||||||
|
for (i, byte) in screen.iter_mut().enumerate() {
|
||||||
|
*byte = if i % 4 == 3 { 255 } else { 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a grid of invaders.
|
/// Create a grid of invaders.
|
||||||
fn make_invader_grid(assets: &Assets) -> Vec<Vec<Option<Invader>>> {
|
fn make_invader_grid(assets: &Assets) -> Vec<Vec<Option<Invader>>> {
|
||||||
use Frame::*;
|
use Frame::*;
|
||||||
|
|
42
src/lib.rs
42
src/lib.rs
|
@ -53,6 +53,7 @@ pub struct Pixels {
|
||||||
texture: wgpu::Texture,
|
texture: wgpu::Texture,
|
||||||
texture_extent: wgpu::Extent3d,
|
texture_extent: wgpu::Extent3d,
|
||||||
texture_format_size: u32,
|
texture_format_size: u32,
|
||||||
|
pixels: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A builder to help create customized pixel buffers.
|
/// A builder to help create customized pixel buffers.
|
||||||
|
@ -124,7 +125,7 @@ impl Pixels {
|
||||||
/// # use pixels::Pixels;
|
/// # use pixels::Pixels;
|
||||||
/// # let surface = wgpu::Surface::create(&pixels_mocks::RWH);
|
/// # let surface = wgpu::Surface::create(&pixels_mocks::RWH);
|
||||||
/// # let surface_texture = pixels::SurfaceTexture::new(1024, 768, surface);
|
/// # let surface_texture = pixels::SurfaceTexture::new(1024, 768, surface);
|
||||||
/// let fb = Pixels::new(320, 240, surface_texture)?;
|
/// let mut pixels = Pixels::new(320, 240, surface_texture)?;
|
||||||
/// # Ok::<(), pixels::Error>(())
|
/// # Ok::<(), pixels::Error>(())
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
@ -169,12 +170,7 @@ impl Pixels {
|
||||||
/// Draw this pixel buffer to the configured [`SurfaceTexture`].
|
/// Draw this pixel buffer to the configured [`SurfaceTexture`].
|
||||||
///
|
///
|
||||||
/// This executes all render passes in sequence. See [`RenderPass`].
|
/// This executes all render passes in sequence. See [`RenderPass`].
|
||||||
///
|
pub fn render(&mut self) {
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `texels` - Byte slice of texture pixels (AKA texels) to draw. The texture format can be
|
|
||||||
/// configured with [`PixelsBuilder`].
|
|
||||||
pub fn render(&mut self, texels: &[u8]) {
|
|
||||||
// TODO: Center frame buffer in surface
|
// TODO: Center frame buffer in surface
|
||||||
let frame = self.swap_chain.get_next_texture();
|
let frame = self.swap_chain.get_next_texture();
|
||||||
let mut encoder = self
|
let mut encoder = self
|
||||||
|
@ -184,8 +180,8 @@ impl Pixels {
|
||||||
// Update the pixel buffer texture view
|
// Update the pixel buffer texture view
|
||||||
let buffer = self
|
let buffer = self
|
||||||
.device
|
.device
|
||||||
.create_buffer_mapped(texels.len(), wgpu::BufferUsage::COPY_SRC)
|
.create_buffer_mapped(self.pixels.len(), wgpu::BufferUsage::COPY_SRC)
|
||||||
.fill_from_slice(texels);
|
.fill_from_slice(&self.pixels);
|
||||||
encoder.copy_buffer_to_texture(
|
encoder.copy_buffer_to_texture(
|
||||||
wgpu::BufferCopyView {
|
wgpu::BufferCopyView {
|
||||||
buffer: &buffer,
|
buffer: &buffer,
|
||||||
|
@ -214,6 +210,26 @@ impl Pixels {
|
||||||
|
|
||||||
self.queue.borrow_mut().submit(&[encoder.finish()]);
|
self.queue.borrow_mut().submit(&[encoder.finish()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a mutable byte slice for the pixel buffer. The buffer is _not_ cleared for you; it will
|
||||||
|
/// retain the previous frame's contents until you clear it yourself.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// # use pixels::Pixels;
|
||||||
|
/// # let surface = wgpu::Surface::create(&pixels_mocks::RWH);
|
||||||
|
/// # let surface_texture = pixels::SurfaceTexture::new(1024, 768, surface);
|
||||||
|
/// let mut pixels = Pixels::new(320, 240, surface_texture)?;
|
||||||
|
/// let frame = pixels.get_frame();
|
||||||
|
/// for pixel in frame {
|
||||||
|
/// *pixel = 0;
|
||||||
|
/// }
|
||||||
|
/// # Ok::<(), pixels::Error>(())
|
||||||
|
/// ```
|
||||||
|
pub fn get_frame(&mut self) -> &mut [u8] {
|
||||||
|
&mut self.pixels
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PixelsBuilder {
|
impl PixelsBuilder {
|
||||||
|
@ -235,7 +251,7 @@ impl PixelsBuilder {
|
||||||
/// # fn render_pass(&self, _: &mut wgpu::CommandEncoder, _: &wgpu::TextureView) {}
|
/// # fn render_pass(&self, _: &mut wgpu::CommandEncoder, _: &wgpu::TextureView) {}
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let fb = PixelsBuilder::new(256, 240, surface_texture)
|
/// let mut pixels = PixelsBuilder::new(256, 240, surface_texture)
|
||||||
/// .pixel_aspect_ratio(8.0 / 7.0)
|
/// .pixel_aspect_ratio(8.0 / 7.0)
|
||||||
/// .add_render_pass(|device, queue, texture| {
|
/// .add_render_pass(|device, queue, texture| {
|
||||||
/// // Create reources for MyRenderPass here
|
/// // Create reources for MyRenderPass here
|
||||||
|
@ -391,6 +407,11 @@ impl PixelsBuilder {
|
||||||
let texture_view = texture.create_default_view();
|
let texture_view = texture.create_default_view();
|
||||||
let texture_format_size = get_texture_format_size(self.texture_format);
|
let texture_format_size = get_texture_format_size(self.texture_format);
|
||||||
|
|
||||||
|
// Create the pixel buffer
|
||||||
|
let capacity = (width * height * texture_format_size) as usize;
|
||||||
|
let mut pixels = Vec::with_capacity(capacity);
|
||||||
|
pixels.resize_with(capacity, Default::default);
|
||||||
|
|
||||||
// Create swap chain
|
// Create swap chain
|
||||||
let surface_texture = self.surface_texture;
|
let surface_texture = self.surface_texture;
|
||||||
let swap_chain = device.create_swap_chain(
|
let swap_chain = device.create_swap_chain(
|
||||||
|
@ -426,6 +447,7 @@ impl PixelsBuilder {
|
||||||
texture,
|
texture,
|
||||||
texture_extent,
|
texture_extent,
|
||||||
texture_format_size,
|
texture_format_size,
|
||||||
|
pixels,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue