我正在尝试用 Piston 进行一些游戏编程,但我正在努力解决opengl_graphics::Texture,因为它不派生Copy或Clone。
extern crate piston_window;
extern crate piston;
extern crate graphics;
extern crate opengl_graphics;
use opengl_graphics::Texture as Tex;
use piston_window::*;
use std::path::Path;
use opengl_graphics::GlGraphics;
#[derive(PartialEq)]
enum ObjectType {
Blocking,
Passing,
}
struct Object {
sprite: Tex,
obj_type: ObjectType,
position: Position,
}
struct Game {
gl: GlGraphics,
images: Vec<Object>,
player: Player,
}
struct Player {
sprite: Tex,
position: Position,
}
struct Position {
x: i32,
y: i32,
}
impl Game {
fn render(&mut self, args: &RenderArgs) {
let iter = self.images.iter();
let player = &self.player;
self.gl.draw(args.viewport(), |c, g| {
clear([1.0, 1.0, 1.0, 1.0], g);
for img in iter {
let pos = img.get_position();
let transform = c.transform.trans(((pos.x * 64)) as f64, ((pos.y * 64)) as f64);
image(img.get_sprite(), transform, g);
}
image(player.get_sprite(),
c.transform.trans((player.get_position().x * 64) as f64,
(player.get_position().y * 64) as f64),
g);
});
}
fn update(&mut self, args: &UpdateArgs) {}
}
Run Code Online (Sandbox Code Playgroud)
主游戏循环:
fn main() {
let (width, height) = (64*10, 64*10);
let opengl = OpenGL::V3_2;
let mut window: PistonWindow =
WindowSettings::new("piston", (width, height))
.exit_on_esc(true)
.opengl(opengl)
.build()
.unwrap();
window.hide();
println!("Loading...");
let mut player = Player { sprite: Tex::from_path(&Path::new(
"./assets/player_n.png")).unwrap(),
position: Position { x: 3, y: 3 },
};
let mut game = Game {
gl: GlGraphics::new(opengl),
images: Vec::new(),
player: player,
};
for i in 0..10 {
for j in 0..10 {
if i == 0 || i == 9 || j == 0 || j == 9 {
let obj = Object { sprite: Tex::from_path(&Path::new(
"./assets/wall.png")).unwrap(),
obj_type: ObjectType::Blocking,
position: Position { x: i, y: j },
};
game.images.push(obj);
} else {
let obj = Object { sprite: Tex::from_path(&Path::new(
"./assets/floor.png")).unwrap(),
obj_type: ObjectType::Passing,
position: Position { x: i, y: j },
};
game.images.push(obj);
}
}
}
window.show();
while let Some(e) = window.next() {
if let Some(Button::Keyboard(key)) = e.press_args() {
let mut pos = game.player.position.clone();
let mut spr: Option<Tex> = None;
match key {
Key::Up => { pos.y -= 1; spr = Some(Tex::from_path(&Path::new(
"./assets/player_n.png")).unwrap()); },
Key::Down => { pos.y += 1; spr = Some(Tex::from_path(&Path::new(
"./assets/player_s.png")).unwrap()); },
Key::Left => { pos.x -= 1; spr = Some(Tex::from_path(&Path::new(
"./assets/player_w.png")).unwrap()); },
Key::Right => { pos.x += 1; spr = Some(Tex::from_path(&Path::new(
"./assets/player_e.png")).unwrap()); },
_ => (),
}
for elem in game.images.iter() {
if pos.x == elem.position.x && pos.y == elem.position.y && elem.obj_type == ObjectType::Passing {
game.player.position = pos;
game.player.sprite = spr.clone().unwrap();
}
}
}
if let Some(r) = e.render_args() {
game.render(&r);
}
if let Some(u) = e.update_args() {
game.update(&u);
}
}
}
Run Code Online (Sandbox Code Playgroud)
产生错误:
extern crate piston_window;
extern crate piston;
extern crate graphics;
extern crate opengl_graphics;
use opengl_graphics::Texture as Tex;
use piston_window::*;
use std::path::Path;
use opengl_graphics::GlGraphics;
#[derive(PartialEq)]
enum ObjectType {
Blocking,
Passing,
}
struct Object {
sprite: Tex,
obj_type: ObjectType,
position: Position,
}
struct Game {
gl: GlGraphics,
images: Vec<Object>,
player: Player,
}
struct Player {
sprite: Tex,
position: Position,
}
struct Position {
x: i32,
y: i32,
}
impl Game {
fn render(&mut self, args: &RenderArgs) {
let iter = self.images.iter();
let player = &self.player;
self.gl.draw(args.viewport(), |c, g| {
clear([1.0, 1.0, 1.0, 1.0], g);
for img in iter {
let pos = img.get_position();
let transform = c.transform.trans(((pos.x * 64)) as f64, ((pos.y * 64)) as f64);
image(img.get_sprite(), transform, g);
}
image(player.get_sprite(),
c.transform.trans((player.get_position().x * 64) as f64,
(player.get_position().y * 64) as f64),
g);
});
}
fn update(&mut self, args: &UpdateArgs) {}
}
Run Code Online (Sandbox Code Playgroud)
我明白为什么会出现此错误,因为opengl_graphics::Texture没有导出Copy我无法克隆Option<opengl_texture>。有什么解决方法吗?
我尝试乱搞参考资料,但没有成功。
如何复制/克隆一个既不派生又不派生的结构?
你不知道。您唯一能做的就是对其进行某种参考。
在这种情况下,图书馆选择不实现Clone或是一件非常好的事情Copy。如果您能够克隆该结构,您将频繁且不必要地分配大量内存。相反,该库迫使您考虑何时分配该内存。解决方案之一是在应用程序启动时加载所有纹理并引用它们:
更改结构以保存引用:
#[derive(PartialEq)]
enum ObjectType {
Blocking,
Passing,
}
struct Object<'a> {
sprite: &'a Tex,
obj_type: ObjectType,
position: Position,
}
struct Game<'a> {
gl: GlGraphics,
images: Vec<Object<'a>>,
player: Player<'a>,
}
struct Player<'a> {
sprite: &'a Tex,
position: Position,
}
#[derive(Copy, Clone, PartialEq)]
struct Position {
x: i32,
y: i32,
}
struct Textures {
player_n: Tex,
player_s: Tex,
player_e: Tex,
player_w: Tex,
wall: Tex,
floor: Tex,
}
Run Code Online (Sandbox Code Playgroud)
尽早加载纹理main。请注意,无需Path显式使用,因为它需要AsRef<Path>:
let textures = Textures {
player_n: Tex::from_path("./assets/player_n.png").unwrap(),
player_s: Tex::from_path("./assets/player_s.png").unwrap(),
player_e: Tex::from_path("./assets/player_e.png").unwrap(),
player_w: Tex::from_path("./assets/player_w.png").unwrap(),
wall: Tex::from_path("./assets/wall.png").unwrap(),
floor: Tex::from_path("./assets/floor.png").unwrap()
};
Run Code Online (Sandbox Code Playgroud)
然后传递对这些纹理的引用:
match key {
Key::Up => {
pos.y -= 1;
spr = Some(&textures.player_n)
}
Key::Down => {
pos.y += 1;
spr = Some(&textures.player_s)
}
Key::Left => {
pos.x -= 1;
spr = Some(&textures.player_w)
}
Key::Right => {
pos.x += 1;
spr = Some(&textures.player_e)
}
_ => (),
}
for elem in game.images.iter() {
if pos == elem.position && elem.obj_type == ObjectType::Passing {
game.player.position = pos;
if let Some(spr) = spr {
game.player.sprite = spr;
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这还合并了可能发生错误的位置。unwrap循环的内部不再存在。
我无法让您的代码完成编译,因为代码不完整,但这应该有助于开始:
#[derive(PartialEq)]
enum ObjectType {
Blocking,
Passing,
}
struct Object<'a> {
sprite: &'a Tex,
obj_type: ObjectType,
position: Position,
}
struct Game<'a> {
gl: GlGraphics,
images: Vec<Object<'a>>,
player: Player<'a>,
}
struct Player<'a> {
sprite: &'a Tex,
position: Position,
}
#[derive(Copy, Clone, PartialEq)]
struct Position {
x: i32,
y: i32,
}
struct Textures {
player_n: Tex,
player_s: Tex,
player_e: Tex,
player_w: Tex,
wall: Tex,
floor: Tex,
}
Run Code Online (Sandbox Code Playgroud)
在某些情况下,您可以将类型包装在Rcor中Arc并克隆它。克隆Rc/Arc只会增加引用计数器,无论底层类型的实现如何Clone(或不存在这样的实现)。