I want to draw a lot of cells based on 2d array in rust piston library. I try to edit hello world example and have function like so:
fn render(&mut self, args: &RenderArgs) {
const GREEN: [f32; 4] = [0.0f32, 1.0f32, 0.0f32, 1.0f32];
const RED: [f32; 4] = [1.0f32, 0.0f32, 0.0f32, 1.0f32];
let square = rectangle::square(0.0, 0.0, 10.0);
let field = &mut self.field;
self.gl.draw(args.viewport(), |c, gl| -> () {
clear(GREEN, gl);
for x_y_item in field {
let item = x_y_item.2;
if item == 7 {
let x = x_y_item.0;
let y = x_y_item.1;
rectangle(
RED,
square,
c.transform.trans(x as f64 * 10.0, y as f64 * 10.0),
gl,
);
}
}
rectangle(
RED,
square,
c.transform.trans(0 as f64 * 10.0, 0 as f64 * 10.0),
gl,
);
})
}
sadly it doesn't work within the loop. as in it works fine if I debug print the variables and hardcode them one by one outside of the loop but inside - it just doesn't draw anything, yet doesn't crash.
Update: I was asked to provide the code to clarify what field is and so it can be runed, so here it is:
Field:
pub struct Grid {
cursor: i32,
body: Vec<Vec<i32>>,
height: i32,
width: i32,
}
impl Grid {
pub fn new(width: i32, height: i32) -> Self {
let mut body: Vec<Vec<i32>> = Vec::with_capacity(height as usize);
let mut temp: Vec<i32> = Vec::with_capacity(width as usize);
for i in 0..width {
temp.push(0);
}
for i in 0..height {
body.push(temp.clone());
}
println!("W: {}, TW:{}, H:{}, TH: {}",width,body[0].len() ,height, body.len());
return Self {cursor: 1 ,width : width, height : height, body : body};
}
pub fn fill(&mut self, value: i32) {
for y in 0..self.height-1 {
for x in 0..self.width - 1 {
self.body[y as usize][x as usize] = value;
}
}
}
pub fn inject(&mut self, pos: (i32,i32), arg: i32) {
self.body[(pos.1 - 1) as usize][(pos.0 - 1) as usize] = arg;
}
pub fn extract(&mut self, pos: (i32,i32)) -> i32 {
return self.body[(pos.1 - 1) as usize][(pos.0 - 1) as usize];
}
pub fn pinpoint(&mut self, val: i32) -> Vec<[i32;2]> {
let mut ret: Vec<[i32;2]> = Vec::new();
for y in 0..self.height {
for x in 0..self.width {
if self.body[y as usize][x as usize] == val {
ret.push([x as i32 + 1,y as i32 + 1]);
}
}
}
return ret;
}
pub fn d_show(&mut self) {
let mut counter: i32 = 1;
for row in self.body.iter() {
println!("{}. {:?}",counter,*row);
counter += 1;
}
}
}
impl Iterator for Grid {
type Item = (i32,i32,i32);
fn next(&mut self) -> Option<Self::Item> {
if self.cursor == self.width * self.height {
return None;
} else {
let x: i32 = self.cursor - (self.cursor/self.width)*self.width;
let y: i32 = self.cursor/self.width;
let val: i32 = 0;
self.cursor += 1;
return Some((x,y,self.body[y as usize][x as usize]));
}
}
}
Main:
extern crate glutin_window;
extern crate graphics;
extern crate opengl_graphics;
extern crate piston;
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{GlGraphics, OpenGL};
use piston::event_loop::{EventSettings, Events};
use piston::input::{RenderArgs, RenderEvent, UpdateArgs, UpdateEvent};
use piston::window::WindowSettings;
use graphics::*;
mod arr2d;
use crate::arr2d::Grid;
pub struct State {
field: arr2d::Grid,
gl: GlGraphics,
}
impl State {
fn render(&mut self, args: &RenderArgs) {
const GREEN: [f32;4] = [0.0f32,1.0f32,0.0f32,1.0f32];
const RED: [f32;4] = [1.0f32,0.0f32,0.0f32,1.0f32];
let square = rectangle::square(0.0,0.0,10.0);
let field = &mut self.field;
self.gl.draw(args.viewport(), |c, gl| -> () {
clear(GREEN,gl);
for x_y_item in field {
let item = x_y_item.2;
if item == 7 {
let x = x_y_item.0;
let y = x_y_item.1;
rectangle(RED, square, c.transform.trans(x as f64 * 10.0, y as f64 * 10.0), gl);
}
}
rectangle(RED, square, c.transform.trans(0 as f64 *10.0,0 as f64 *10.0), gl);
})
}
fn update(&mut self, args: &UpdateArgs) {
}
fn new(gl: OpenGL ,w: i32,h: i32) -> Self {
let mut body = Grid::new(w,h);
body.inject((4,4),7);
body.inject((4,5),7);
body.inject((4,6),7);
return Self{gl: GlGraphics::new(gl), field: body};
}
}
fn main() {
let open_gl = OpenGL::V3_2;
let mut window : Window = WindowSettings::new("Spinning Square",[200,200])
.opengl(open_gl)
.exit_on_esc(true)
.build()
.unwrap();
let mut app = State::new(open_gl,20,20);
let mut events = Events::new(EventSettings::new());
while let Some(e) = events.next(&mut window) {
if let Some(args) = e.render_args() {
app.render(&args);
}
if let Some(args) = e.update_args() {
app.update(&args);
}
}
}
Update #2:
I did more research - and created much simpler version of the code based on other tutorials and examples, but that issue still seem to persist:
extern crate piston;
use piston_window::*;
use std::ffi::OsString;
use std::path::Path;
mod tileSet;
mod arr2d;
fn main() {
let mut window: PistonWindow = WindowSettings::new("Hello Piston!", [640, 480]).exit_on_esc(true)
.build()
.unwrap();
let mut tilez: tileSet::Textures = tileSet::Textures::from_directory(OsString::from("C:\\Users\\grass\\Desktop\\codes\\Rust\\ghandalf\\assets"),
window.create_texture_context(),
|x: &Path| -> bool {
return x.to_str().unwrap().ends_with(".png");
}
);
let mut field: arr2d::Grid = arr2d::Grid::new(40,40);
field.fill(0);
let mut image: Image = Image::new();
while let Some(event) = window.next() {
window.draw_2d(&event, |context, graphics, _device| {
clear([1.0; 4], graphics);
for (x,y,item) in &mut field {
let tile: String = match item {
0 => "tile0.png".to_string(),
_ => "tile1.png".to_string()
};
image.draw(tilez.get(tile).unwrap(), &DrawState::default(), context.transform.trans(40.0,40.0), graphics); //empty screen here
}
image.draw(tilez.get(tile).unwrap(), &DrawState::default(), context.transform.trans(40.0,40.0), graphics); //works fine here
});
}
}
I tried using hardcoded variables, debugging whether the loop iterates, check if any variable is out of scope but it doesn't seem to give the answer. I think that it has to do with some open gl concept like clearing the screen per iteration perhaps?
It doesn't help that compiler doesn't throw an error.
field
is. As a wild guess, though, I suspect you might be providing display coordinates when the GL context expects normalized device coordinates. – Cormac O'Brien