Skip to content

Instantly share code, notes, and snippets.

@DarinM223
Created May 1, 2017 22:06
Show Gist options
  • Save DarinM223/331bccf50ef269b68db491106c473c31 to your computer and use it in GitHub Desktop.
Save DarinM223/331bccf50ef269b68db491106c473c31 to your computer and use it in GitHub Desktop.
Mold2d Profile results
1190ms of 1320ms total (90.15%)
Showing top 10 nodes out of 61 (cum >= 890ms)
flat flat% sum% cum cum%
650ms 49.24% 49.24% 850ms 64.39% [nouveau_dri.so]
130ms 9.85% 59.09% 1320ms 100% [libc-2.23.so]
80ms 6.06% 65.15% 1320ms 100% [game]
70ms 5.30% 70.45% 120ms 9.09% [libdrm_nouveau.so.2.0.0]
60ms 4.55% 75.00% 930ms 70.45% [libSDL2-2.0.so.0.4.0]
50ms 3.79% 78.79% 50ms 3.79% [libpthread-2.23.so]
50ms 3.79% 82.58% 200ms 15.15% update
40ms 3.03% 85.61% 80ms 6.06% constrain_to_viewport
30ms 2.27% 87.88% 30ms 2.27% collides_with
30ms 2.27% 90.15% 890ms 67.42% render
ROUTINE ======================== update in /home/d/Documents/git/rust/mold2d/examples/mario/src/actors/koopa.rs
0 20ms (flat, cum) 0.32% of Total
. . 201: };
. . 202:
. . 203: self.curr_speed = (KOOPA_ACCELERATION * target_speed) + self.curr_speed;
. . 204:
. . 205: let mut change = PositionChange::new().left(self.curr_speed.x as i32);
. 20ms 206: if self.curr_state == KoopaState::Jumping {
. . 207: change = change.down(self.curr_speed.y as i32);
. . 208: }
. . 209:
. . 210: // If actor is no longer grounded, change it to jumping
. . 211: if !self.grounded && self.curr_state != KoopaState::Jumping {
ROUTINE ======================== update in /home/d/Documents/git/rust/mold2d/examples/mario/src/actors/player.rs
0 30ms (flat, cum) 0.48% of Total
. . 199: if context.events.event_called_once("SPACE") && self.curr_state != PlayerState::Jumping {
. . 200: self.curr_speed.y = -PLAYER_JUMP_VELOCITY;
. . 201: self.curr_state = PlayerState::Jumping;
. . 202: }
. . 203:
. 10ms 204: let max_x_speed = if context.events.event_called("RIGHT") {
. . 205: if self.curr_state == PlayerState::Idle {
. . 206: self.curr_state = PlayerState::Walking;
. . 207: }
. . 208: self.direction = Direction::Right;
. . 209:
. . 210: -PLAYER_X_MAXSPEED
. . 211: } else if context.events.event_called("LEFT") {
. . 212: if self.curr_state == PlayerState::Idle {
. . 213: self.curr_state = PlayerState::Walking;
. . 214: }
. . 215: self.direction = Direction::Left;
. . 216:
. . 217: PLAYER_X_MAXSPEED
. . 218: } else {
. . 219: if self.curr_state == PlayerState::Walking {
. . 220: self.curr_state = PlayerState::Idle;
. . 221: }
. . 222:
. . 223: 0.0
. . 224: };
. . 225:
. . 226: let max_y_speed = if self.curr_state == PlayerState::Jumping {
. . 227: PLAYER_Y_MAXSPEED
. . 228: } else {
. . 229: 0.
. . 230: };
. . 231:
. . 232: let target_speed = Vector2D {
. . 233: x: max_x_speed,
. . 234: y: max_y_speed,
. . 235: };
. . 236:
. . 237: self.curr_speed = (PLAYER_ACCELERATION * target_speed) +
. . 238: ((1.0 - PLAYER_ACCELERATION) * self.curr_speed);
. . 239:
. . 240: // Apply position change
. . 241: let mut change = PositionChange::new().left(self.curr_speed.x as i32);
. . 242: if self.curr_state == PlayerState::Jumping {
. . 243: change = change.down(self.curr_speed.y as i32);
. . 244: }
. . 245:
. . 246: // If not grounded, change to jumping
. . 247: if !self.grounded && self.curr_state != PlayerState::Jumping {
. . 248: self.curr_state = PlayerState::Jumping;
. . 249: }
. . 250:
. . 251: // Reset grounded collision
. . 252: if self.grounded {
. . 253: self.grounded = false;
. . 254: }
. . 255:
. . 256: // Update sprite animation
. . 257: let key = (self.size, self.curr_state, self.direction);
. 10ms 258: self.anims.add_time(&key, elapsed);
. . 259:
. . 260: self.prev_segment = Some(Segment {
. 10ms 261: point: (self.data().rect.x() as f64, self.data().rect.y() as f64),
. . 262: vector: change.to_vector(),
. . 263: });
. . 264:
. . 265: change
. . 266: }
ROUTINE ======================== update in /home/d/Documents/git/rust/mold2d/examples/mario/src/views/game_view.rs
10ms 3.81s (flat, cum) 60.57% of Total
. . 81: }
. . 82: }
. . 83:
. . 84: #[inline]
. . 85: fn update(&mut self, context: &mut Context, elapsed: f64) -> Option<ViewAction> {
10ms 20ms 86: if context.events.event_called("QUIT") || context.events.event_called("ESC") {
. . 87: return Some(ViewAction::Quit);
. . 88: }
. . 89:
. . 90: if context.events.event_called_once("ENTER") {
. . 91: return Some(ViewAction::ChangeView(Box::new(BackgroundView)));
. . 92: }
. . 93:
. . 94: {
. . 95: let window_rect = Rect::new(0, 0, context.window.width, context.window.height);
. . 96: let viewport_clone = self.viewport.clone();
. . 97: let mut quadtree = Quadtree::new(window_rect, &viewport_clone);
. . 98: let mut keys = Vec::with_capacity(self.actors.actors.len());
. . 99:
. 70ms 100: for (key, actor) in &mut self.actors.actors {
. 180ms 101: let data = actor.data().clone();
. . 102:
. 210ms 103: if let Some(_) = self.viewport.constrain_to_viewport(&data.rect) {
. 10ms 104: keys.push(key.clone());
. 380ms 105: quadtree.insert(data);
. . 106: }
. . 107: }
. . 108:
. 20ms 109: for key in keys {
. 670ms 110: let actor = self.actors.temp_remove(key);
. . 111: if let Some(mut actor) = actor {
. 100ms 112: let data = actor.data();
. . 113:
. . 114: // update the actor
. 50ms 115: let pos_change = actor.update(context, elapsed);
. 20ms 116: actor.handle_message(&ActorMessage::ActorAction {
. . 117: send_id: data.id,
. . 118: recv_id: data.id,
. . 119: action: ActorAction::ChangePosition(pos_change),
. 10ms 120: });
. . 121:
. 10ms 122: if data.collision_filter != 0 && data.actor_type != ActorType::Block {
. . 123: // only check collisions for nearby actors
. 490ms 124: let nearby_actors = quadtree.retrieve(&data.rect)
. . 125: .into_iter()
. . 126: .map(|act| act.clone())
. . 127: .collect::<Vec<_>>();
. 80ms 128: for other in nearby_actors {
. 420ms 129: if let Some(direction) = actor.collides_with(&other) {
. 230ms 130: handle_collision(&mut actor,
. . 131: &other,
. . 132: direction,
. . 133: Box::new(handle_message),
. . 134: &mut self.actors,
. . 135: &mut self.viewport,
. . 136: context);
. . 137: }
. 10ms 138: }
. . 139: }
. . 140:
. 810ms 141: self.actors.temp_reinsert(actor.data().id, actor);
. . 142:
. . 143: if data.actor_type == ActorType::Player {
. . 144: self.viewport.set_position((data.rect.x(), data.rect.y()));
. . 145: }
. . 146: }
. . 147: }
. 20ms 148: }
. . 149:
. . 150: None
. . 151: }
. . 152:}
ROUTINE ======================== constrain_to_viewport in /home/d/Documents/git/rust/mold2d/src/viewport.rs
210ms 840ms (flat, cum) 13.35% of Total
. . 62: (map_point.0 - self.x, map_point.1 - self.y)
. . 63: }
. . 64:
. . 65: /// Returns a rectangle in viewport coordinates or None if not in viewport
. . 66: pub fn constrain_to_viewport(&self, rect: &Rect) -> Option<Rect> {
20ms 20ms 67: let rect_points = [(rect.x(), rect.y()),
20ms 30ms 68: (rect.x() + (rect.width() as i32), rect.y()),
10ms 10ms 69: (rect.x(), rect.y() + (rect.height() as i32)),
10ms 30ms 70: (rect.x() + (rect.width() as i32), rect.y() + (rect.height() as i32))];
. . 71:
. . 72: let mut in_viewport = false;
40ms 360ms 73: for point in rect_points.iter() {
60ms 120ms 74: if self.in_viewport(*point) {
. . 75: in_viewport = true;
. . 76: break;
. . 77: }
. . 78: }
. . 79:
. . 80: if in_viewport {
10ms 70ms 81: let center = center_point(rect);
30ms 50ms 82: let (x, y) = self.relative_point((center.0 as i32, center.1 as i32));
10ms 150ms 83: Some(Rect::new(x, y, rect.width(), rect.height()))
. . 84: } else {
. . 85: None
. . 86: }
. . 87: }
. . 88:}
ROUTINE ======================== collides_with in /home/d/Documents/git/rust/mold2d/examples/mario/src/actors/koopa.rs
0 410ms (flat, cum) 6.52% of Total
. . 183: }
. . 184: }
. . 185:
. . 186: fn collides_with(&mut self, other: &ActorData) -> Option<CollisionSide> {
. . 187: let key = (self.curr_state, self.size, self.direction);
. 410ms 188: self.anims.collides_with(&key, &other.bounding_box)
. . 189: }
. . 190:
. . 191: fn update(&mut self, _context: &mut Context, _elapsed: f64) -> PositionChange {
. . 192: let max_y_speed = if self.curr_state == KoopaState::Jumping {
. . 193: KOOPA_Y_MAXSPEED
ROUTINE ======================== collides_with in /home/d/Documents/git/rust/mold2d/examples/mario/src/actors/player.rs
0 30ms (flat, cum) 0.48% of Total
. . 180: }
. . 181: }
. . 182:
. . 183: fn collides_with(&mut self, other: &ActorData) -> Option<CollisionSide> {
. . 184: let key = (self.size, self.curr_state, self.direction);
. 30ms 185: self.anims.collides_with(&key, &other.bounding_box)
. . 186: }
. . 187:
. . 188: fn update(&mut self, context: &mut Context, elapsed: f64) -> PositionChange {
. . 189: if context.events.event_called("DOWN") {
. . 190: if self.size == PlayerSize::Big && self.curr_state != PlayerState::Jumping {
ROUTINE ======================== collides_with in /home/d/Documents/git/rust/mold2d/src/collision.rs
100ms 1.02s (flat, cum) 16.22% of Total
. . 155: fn collides_with(&self, other: T) -> Option<CollisionSide>;
. . 156:}
. . 157:
. . 158:impl Collision<Rect> for Rect {
. . 159: fn collides_with(&self, other: Rect) -> Option<CollisionSide> {
10ms 20ms 160: let w = 0.5 * (self.width() + other.width()) as f64;
20ms 30ms 161: let h = 0.5 * (self.height() + other.height()) as f64;
. . 162: let dx = center_point(self).0 - center_point(&other).0;
20ms 60ms 163: let dy = center_point(self).1 - center_point(&other).1;
. . 164:
. . 165: if dx.abs() <= w && dy.abs() <= h {
. . 166: let wy = w * dy;
. . 167: let hx = h * dx;
. . 168:
. . 169: if wy > hx {
. . 170: if wy > -hx {
. . 171: return Some(CollisionSide::Top);
. . 172: } else {
. . 173: return Some(CollisionSide::Right);
. . 174: }
. . 175: } else {
. . 176: if wy > -hx {
. . 177: return Some(CollisionSide::Left);
. . 178: } else {
. . 179: return Some(CollisionSide::Bottom);
. . 180: }
. . 181: }
. . 182: }
. . 183:
. . 184: None
. . 185: }
. . 186:}
. . 187:
. . 188:impl Collision<SpriteRectangle> for Rect {
. . 189: fn collides_with(&self, other: SpriteRectangle) -> Option<CollisionSide> {
. . 190: if let Some(rect) = other.to_sdl() {
. . 191: return self.collides_with(rect);
. . 192: }
. . 193:
. . 194: None
. . 195: }
. . 196:}
. . 197:
. . 198:impl Collision<Rect> for SpriteRectangle {
. . 199: fn collides_with(&self, other: Rect) -> Option<CollisionSide> {
. 110ms 200: if let Some(rect) = self.to_sdl() {
. 110ms 201: return rect.collides_with(other);
. . 202: }
. . 203:
. . 204: None
. . 205: }
. . 206:}
. . 207:
. . 208:impl Collision<SpriteRectangle> for SpriteRectangle {
10ms 10ms 209: fn collides_with(&self, other: SpriteRectangle) -> Option<CollisionSide> {
. 80ms 210: if let Some(rect) = other.to_sdl() {
. 220ms 211: return self.collides_with(rect);
. . 212: }
. . 213:
. . 214: None
. . 215: }
. . 216:}
. . 217:
. . 218:#[derive(Clone, PartialEq)]
. . 219:pub enum BoundingBox {
. . 220: Rectangle(SpriteRectangle),
. . 221:}
. . 222:
. . 223:impl BoundingBox {
. . 224: pub fn apply_change(&mut self, change: &PositionChange) {
. . 225: match *self {
. . 226: BoundingBox::Rectangle(ref mut rect) => {
. . 227: rect.x += change.x;
. . 228: rect.y += change.y;
. . 229: }
. . 230: }
. . 231: }
. . 232:}
. . 233:
. . 234:impl<'a> Collision<&'a BoundingBox> for BoundingBox {
30ms 30ms 235: fn collides_with(&self, other: &'a BoundingBox) -> Option<CollisionSide> {
. . 236: match (self, other) {
. . 237: (&BoundingBox::Rectangle(ref rect1), &BoundingBox::Rectangle(ref rect2)) => {
. . 238: // TODO(DarinM223): avoid cloning the second rectangle
10ms 350ms 239: rect1.collides_with(rect2.clone())
. . 240: }
. . 241: }
. . 242: }
. . 243:}
. . 244:
ROUTINE ======================== collides_with<(game::actors::koopa::KoopaState, game::actors::koopa::KoopaSize, mold2d::sprite::Direction)> in /home/d/Documents/git/rust/mold2d/src/sprite.rs
10ms 410ms (flat, cum) 6.52% of Total
. . 376: /// and returns the side of the collision if it happens
. . 377: pub fn collides_with(&mut self,
. . 378: s: &State,
. . 379: other_bbox: &Option<BoundingBox>)
. . 380: -> Option<CollisionSide> {
. 50ms 381: if let Some(bounding_box) = self.bbox(s) {
. . 382: if let Some(ref bbox) = *other_bbox {
10ms 360ms 383: return bounding_box.collides_with(bbox);
. . 384: }
. . 385: }
. . 386:
. . 387: None
. . 388: }
ROUTINE ======================== collides_with<(game::actors::player::PlayerSize, game::actors::player::PlayerState, mold2d::sprite::Direction)> in /home/d/Documents/git/rust/mold2d/src/sprite.rs
0 30ms (flat, cum) 0.48% of Total
. . 378: s: &State,
. . 379: other_bbox: &Option<BoundingBox>)
. . 380: -> Option<CollisionSide> {
. . 381: if let Some(bounding_box) = self.bbox(s) {
. . 382: if let Some(ref bbox) = *other_bbox {
. 30ms 383: return bounding_box.collides_with(bbox);
. . 384: }
. . 385: }
. . 386:
. . 387: None
. . 388: }
ROUTINE ======================== render in /home/d/Documents/git/rust/mold2d/examples/mario/src/actors/coin.rs
0 10ms (flat, cum) 0.16% of Total
. . 75: fn render(&mut self, context: &mut Context, viewport: &mut Viewport, _elapsed: f64) {
. . 76: let (rx, ry) = viewport.relative_point((self.rect.x, self.rect.y));
. . 77: let rect = Rect::new(rx, ry, self.rect.w, self.rect.h);
. . 78:
. . 79: // Render sprite animation
. 10ms 80: self.animation.render(&mut context.renderer, rect);
. . 81: }
. . 82:
. . 83: fn data(&mut self) -> ActorData {
. . 84: ActorData {
. . 85: id: self.id,
ROUTINE ======================== render in /home/d/Documents/git/rust/mold2d/examples/mario/src/actors/koopa.rs
0 60ms (flat, cum) 0.95% of Total
. . 225: change
. . 226: }
. . 227:
. . 228: fn render(&mut self, context: &mut Context, viewport: &mut Viewport, _elapsed: f64) {
. . 229: let key = (self.curr_state, self.size, self.direction);
. 60ms 230: self.anims.render(&key, &self.rect, viewport, &mut context.renderer, false);
. . 231: }
. . 232:
. . 233: fn data(&mut self) -> ActorData {
. . 234: ActorData {
. . 235: id: self.id,
ROUTINE ======================== render in /home/d/Documents/git/rust/mold2d/examples/mario/src/actors/player.rs
0 10ms (flat, cum) 0.16% of Total
. . 276: side.render(Color::RGB(0, 255, 0), viewport, &mut context.renderer);
. . 277: }
. . 278: }
. . 279:
. . 280: let key = (self.size, self.curr_state, self.direction);
. 10ms 281: self.anims.render(&key, &self.rect, viewport, &mut context.renderer, false);
. . 282: }
. . 283:
. . 284: fn data(&mut self) -> ActorData {
. . 285: ActorData {
. . 286: id: self.id,
ROUTINE ======================== render in /home/d/Documents/git/rust/mold2d/examples/mario/src/views/game_view.rs
20ms 2.17s (flat, cum) 34.50% of Total
. . 42:impl View for GameView {
. . 43: #[inline]
. . 44: fn render(&mut self, context: &mut Context, elapsed: f64) {
. . 45: // start off with a black screen
. . 46: context.renderer.set_draw_color(Color::RGB(135, 206, 250));
. 40ms 47: context.renderer.clear();
. . 48:
. . 49: // render contained actors
. 100ms 50: for (_, actor) in &mut self.actors.actors {
20ms 570ms 51: if let Some(_) = self.viewport.constrain_to_viewport(&actor.data().rect) {
. 1.42s 52: actor.render(context, &mut self.viewport, elapsed);
. . 53: }
. . 54: }
. . 55:
. . 56: // render score
. 20ms 57: if let Some(score) = context.score.score("GAME_SCORE") {
. . 58: let score_text = format!("Score: {}", score);
. . 59: let mut had_cached_score = false;
. . 60:
. . 61: if let Some(ref prev_score) = self.cached_score {
. . 62: if *prev_score == score_text {
. . 63: if let Some(ref font_sprite) = self.cached_font_sprite {
. 10ms 64: font::render_text(&mut context.renderer, font_sprite, (100, 100));
. . 65: }
. . 66: had_cached_score = true;
. . 67: }
. . 68: }
. . 69:
. . 70: if !had_cached_score {
. 10ms 71: let font_sprite = font::text_sprite(&context.renderer,
. . 72: &score_text[..],
. . 73: "assets/belligerent.ttf",
. . 74: 32,
. . 75: Color::RGB(0, 255, 0))
. . 76: .unwrap();
ROUTINE ======================== render in /home/d/Documents/git/rust/mold2d/src/sprite.rs
20ms 1.46s (flat, cum) 23.21% of Total
. . 146: }
. . 147:}
. . 148:
. . 149:impl Renderable for Sprite {
. . 150: /// Render the sprite image onto the rectangle
10ms 10ms 151: fn render(&self, renderer: &mut Renderer, dest: Rect) {
10ms 1.38s 152: renderer.copy(&mut self.tex.borrow_mut(), Some(self.src), Some(dest));
. . 153: }
. . 154:}
. . 155:
. . 156:/// Represents an animated sprite with multiple frames
. . 157:#[derive(Clone)]
. . 158:pub struct AnimatedSprite {
. . 159: /// Frames that will be rendered
. . 160: frames: Vec<Sprite>,
. . 161: /// Time between frames
. . 162: frame_delay: f64,
. . 163: /// Total time sprite has been alive
. . 164: current_time: f64,
. . 165:}
. . 166:
. . 167:impl AnimatedSprite {
. . 168: /// Creates a new animated sprite with the given Sprite frames and a frame delay
. . 169: fn new(frames: Vec<Sprite>, frame_delay: f64) -> AnimatedSprite {
. . 170: AnimatedSprite {
. . 171: frames: frames,
. . 172: frame_delay: frame_delay,
. . 173: current_time: 0.0,
. . 174: }
. . 175: }
. . 176:
. . 177: pub fn with_fps(frames: Vec<Sprite>, fps: f64) -> AnimatedSprite {
. . 178: assert!(fps != 0.0);
. . 179: AnimatedSprite::new(frames, 1.0 / fps)
. . 180: }
. . 181:
. . 182: fn set_frame_delay(&mut self, frame_delay: f64) {
. . 183: self.frame_delay = frame_delay;
. . 184: }
. . 185:
. . 186: fn set_fps(&mut self, fps: f64) {
. . 187: assert!(fps != 0.0);
. . 188: self.set_frame_delay(1.0 / fps);
. . 189: }
. . 190:
. . 191: /// Updates the animated sprite with the elapsed time
. . 192: pub fn add_time(&mut self, elapsed: f64) {
. . 193: self.current_time += elapsed;
. . 194:
. . 195: if self.current_time < 0.0 {
. . 196: self.current_time = (self.frames.len() - 1) as f64 * self.frame_delay;
. . 197: }
. . 198: }
. . 199:}
. . 200:
. . 201:impl Renderable for AnimatedSprite {
. . 202: /// Renders the current frame of the animated sprite
. . 203: fn render(&self, renderer: &mut Renderer, dest: Rect) {
. . 204: assert!(self.frames.len() > 0, "There as to be at least one frame!");
. . 205: let current_frame = (self.current_time / self.frame_delay) as usize % self.frames.len();
. . 206:
. 10ms 207: let frame = &self.frames[current_frame];
. 60ms 208: frame.render(renderer, dest);
. . 209: }
. . 210:}
. . 211:
. . 212:/// Contains configuration fields for parsing a spritesheet
. . 213:pub struct SpritesheetConfig {
ROUTINE ======================== render<(game::actors::koopa::KoopaState, game::actors::koopa::KoopaSize, mold2d::sprite::Direction)> in /home/d/Documents/git/rust/mold2d/src/sprite.rs
0 60ms (flat, cum) 0.95% of Total
. . 414: }
. . 415:
. . 416: let (rx, ry) = viewport.relative_point((rect.x, rect.y));
. . 417: let rect = Rect::new(rx, ry, rect.w, rect.h);
. . 418:
. 60ms 419: self.anim_mut(s).unwrap().render(renderer, rect);
. . 420: }
. . 421:}
ROUTINE ======================== render<(game::actors::player::PlayerSize, game::actors::player::PlayerState, mold2d::sprite::Direction)> in /home/d/Documents/git/rust/mold2d/src/sprite.rs
0 10ms (flat, cum) 0.16% of Total
. . 414: }
. . 415:
. . 416: let (rx, ry) = viewport.relative_point((rect.x, rect.y));
. . 417: let rect = Rect::new(rx, ry, rect.w, rect.h);
. . 418:
. 10ms 419: self.anim_mut(s).unwrap().render(renderer, rect);
. . 420: }
. . 421:}
ROUTINE ======================== render_text in /home/d/Documents/git/rust/mold2d/src/font.rs
0 10ms (flat, cum) 0.16% of Total
. . 51:
. . 52:/// Renders a text sprite at the specified point
. . 53:pub fn render_text(renderer: &mut Renderer, sprite: &Sprite, point: (i32, i32)) {
. . 54: let (x, y) = point;
. . 55: let (w, h) = sprite.size();
. 10ms 56: sprite.render(renderer, Rect::new(x, y, w, h));
. . 57:}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment