Update public API to provide &mut [u8] instead of accepting &[u8] from the app (#22)

- Closes #19
This commit is contained in:
Jay Oster 2019-10-21 23:17:58 -07:00 committed by GitHub
parent b18690f19f
commit 8801bad58a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 39 deletions

View file

@ -42,7 +42,7 @@ fn main() -> Result<(), Error> {
};
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 time = Instant::now();
let mut controls = Controls::default();
@ -54,7 +54,8 @@ fn main() -> Result<(), Error> {
event: WindowEvent::RedrawRequested,
..
} => {
pixels.render(invaders.draw());
invaders.draw(pixels.get_frame());
pixels.render();
}
_ => (),
}

View file

@ -48,7 +48,6 @@ pub struct World {
collision: Collision,
score: u32,
assets: Assets,
screen: Vec<u8>,
dt: Duration,
gameover: bool,
random: OsRng,
@ -149,10 +148,6 @@ impl World {
let collision = Collision::default();
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 gameover = false;
let random = OsRng;
@ -166,7 +161,6 @@ impl World {
collision,
score,
assets,
screen,
dt,
gameover,
random,
@ -261,47 +255,45 @@ impl World {
/// Draw the internal state to the screen.
///
/// 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
self.clear();
clear(screen);
// Draw the invaders
for row in &self.invaders.grid {
for col in row {
if let Some(invader) = col {
blit(&mut self.screen, &invader.pos, &invader.sprite);
blit(screen, &invader.pos, &invader.sprite);
}
}
}
// Draw the shields
for shield in &self.shields {
blit(&mut self.screen, &shield.pos, &shield.sprite);
blit(screen, &shield.pos, &shield.sprite);
}
// Draw the player
blit(&mut self.screen, &self.player.pos, &self.player.sprite);
blit(screen, &self.player.pos, &self.player.sprite);
// Draw the bullet
if let Some(bullet) = &self.bullet {
blit(&mut self.screen, &bullet.pos, &bullet.sprite);
blit(screen, &bullet.pos, &bullet.sprite);
}
// Draw lasers
for laser in self.lasers.iter() {
blit(&mut self.screen, &laser.pos, &laser.sprite);
blit(screen, &laser.pos, &laser.sprite);
}
// Draw debug information
if self.debug {
debug::draw_invaders(&mut self.screen, &self.invaders, &self.collision);
debug::draw_bullet(&mut self.screen, self.bullet.as_ref());
debug::draw_lasers(&mut self.screen, &self.lasers);
debug::draw_player(&mut self.screen, &self.player, &self.collision);
debug::draw_shields(&mut self.screen, &self.shields, &self.collision);
debug::draw_invaders(screen, &self.invaders, &self.collision);
debug::draw_bullet(screen, self.bullet.as_ref());
debug::draw_lasers(screen, &self.lasers);
debug::draw_player(screen, &self.player, &self.collision);
debug::draw_shields(screen, &self.shields, &self.collision);
}
&self.screen
}
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 {
@ -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.
fn make_invader_grid(assets: &Assets) -> Vec<Vec<Option<Invader>>> {
use Frame::*;

View file

@ -53,6 +53,7 @@ pub struct Pixels {
texture: wgpu::Texture,
texture_extent: wgpu::Extent3d,
texture_format_size: u32,
pixels: Vec<u8>,
}
/// A builder to help create customized pixel buffers.
@ -124,7 +125,7 @@ impl Pixels {
/// # use pixels::Pixels;
/// # let surface = wgpu::Surface::create(&pixels_mocks::RWH);
/// # 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>(())
/// ```
///
@ -169,12 +170,7 @@ impl Pixels {
/// Draw this pixel buffer to the configured [`SurfaceTexture`].
///
/// This executes all render passes in sequence. See [`RenderPass`].
///
/// # 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]) {
pub fn render(&mut self) {
// TODO: Center frame buffer in surface
let frame = self.swap_chain.get_next_texture();
let mut encoder = self
@ -184,8 +180,8 @@ impl Pixels {
// Update the pixel buffer texture view
let buffer = self
.device
.create_buffer_mapped(texels.len(), wgpu::BufferUsage::COPY_SRC)
.fill_from_slice(texels);
.create_buffer_mapped(self.pixels.len(), wgpu::BufferUsage::COPY_SRC)
.fill_from_slice(&self.pixels);
encoder.copy_buffer_to_texture(
wgpu::BufferCopyView {
buffer: &buffer,
@ -214,6 +210,26 @@ impl Pixels {
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 {
@ -235,7 +251,7 @@ impl PixelsBuilder {
/// # 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)
/// .add_render_pass(|device, queue, texture| {
/// // Create reources for MyRenderPass here
@ -391,6 +407,11 @@ impl PixelsBuilder {
let texture_view = texture.create_default_view();
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
let surface_texture = self.surface_texture;
let swap_chain = device.create_swap_chain(
@ -426,6 +447,7 @@ impl PixelsBuilder {
texture,
texture_extent,
texture_format_size,
pixels,
})
}
}