Sign in to follow this  
Hendrik

Trailing objects in PIXI

Recommended Posts

Hey there, i am new to JS and PIXI and tried to rebuild a pong game in PIXI.JS to make it responsive. (https://robots.thoughtbot.com/pong-clone-in-javascript)

It seems to work but i run into the issue that all elements have a trail on movement, do i have to rerender the stage to avoid the trail or am i missing something?

https://jsfiddle.net/02utycqq/


// define gamne variables
const appWidth = window.innerWidth;
const appHeight = window.innerHeight;
const paddleWidth = 50;
const paddleHeight = 10;
const ballSize = 5;
const appWidthHalf = appWidth / 2;
const appHeightHalf = appHeight / 2;
const paddleWidthHalf = paddleWidth / 2;
const pongColor = 0x57dfbf;
const computerPositionX = appWidthHalf - paddleWidthHalf;
const computerPositionY = 50;
const playerPositionX = computerPositionX;
const playerPositionY = appHeight - computerPositionY - paddleHeight;
const ballPositionX = appWidthHalf;
const ballPositionY = appHeightHalf;
const playerSpeed = 4;
const computerSpeed = 4;
const ballSpeed = 3;

// Setup the ticker and the root stage PIXI.Container.
const app = new PIXI.Application(appWidth, appHeight, {
  antialias: false,
  transparent: false,
  resolution: 1,
});

function Paddle(x, y, width, height) {
  this.x = x;
  this.y = y;
  this.width = width;
  this.height = height;
  this.x_speed = 0;
  this.y_speed = 0;
}

Paddle.prototype.render = function renderPaddle() {
  this.graphics = new PIXI.Graphics();
  this.graphics.beginFill(pongColor);
  this.graphics.drawRect(this.x, this.y, this.width, this.height);
  this.graphics.endFill();
  app.stage.addChild(this.graphics);
};

Paddle.prototype.move = function (x, y) {
  this.x += x;
  this.y += y;
  this.x_speed = x;
  this.y_speed = y;
  if (this.x < 0) {
    this.x = 0;
    this.x_speed = 0;
  } else if (this.x + this.width > appWidth) {
    this.x = appWidth - this.width;
    this.x_speed = 0;
  }
};

function Player() {
  this.paddle = new Paddle(playerPositionX, playerPositionY, paddleWidth, paddleHeight);
}

Player.prototype.render = function renderPlayer() {
  this.paddle.render();
};

Player.prototype.update = function () {
  for (const key in keysDown) {
    const value = Number(key);
    if (value === 37) {
      this.paddle.move(-playerSpeed, 0);
    } else if (value === 39) {
      this.paddle.move(playerSpeed, 0);
    } else {
      this.paddle.move(0, 0);
    }
  }
};

function Computer() {
  this.paddle = new Paddle(computerPositionX, computerPositionY, paddleWidth, paddleHeight);
}

Computer.prototype.render = function renderComputer() {
  this.paddle.render();
};

Computer.prototype.update = function (ball) {
  const x_pos = ball.x;
  // eslint-disable-next-line
  let diff = -(this.paddle.x + this.paddle.width / 2 - x_pos);
  if (diff < 0 && diff < -computerSpeed) {
    diff = -ballSize;
  } else if (diff > 0 && diff > computerSpeed) {
    diff = ballSize;
  }
  this.paddle.move(diff, 0);
  if (this.paddle.x < 0) {
    this.paddle.x = 0;
  } else if (this.paddle.x + this.paddle.width > appWidth) {
    this.paddle.x = appWidth - this.paddle.width;
  }
};

function Ball(x, y) {
  this.x = x;
  this.y = y;
  this.width = ballSize;
  this.height = ballSize;
  this.x_speed = 0;
  this.y_speed = ballSpeed;
}

Ball.prototype.render = function renderBall() {
  this.graphics = new PIXI.Graphics();
  this.graphics.beginFill(pongColor);
  this.graphics.drawRect(this.x, this.y, this.width, this.height);
  this.graphics.endFill();
  app.stage.addChild(this.graphics);
};

Ball.prototype.update = function (paddle1, paddle2) {
  this.x += this.x_speed;
  this.y += this.y_speed;
  const top_x = this.x - ballSize;
  const top_y = this.y - ballSize;
  const bottom_x = this.x + ballSize;
  const bottom_y = this.y + ballSize;

  if (this.x - ballSize < 0) {
    this.x = ballSize;
    this.x_speed = -this.x_speed;
  } else if (this.x + ballSize > appWidth) {
    this.x = appWidth - ballSize;
    this.x_speed = -this.x_speed;
  }

  if (this.y < 0 || this.y > appHeight) {
    this.x_speed = 0;
    this.y_speed = ballSpeed;
    this.x = appWidthHalf;
    this.y = appHeightHalf;
  }

  if (top_y > appHeightHalf) {
    if (
      top_y < paddle1.y + paddle1.height &&
      bottom_y > paddle1.y &&
      top_x < paddle1.x + paddle1.width &&
      bottom_x > paddle1.x
    ) {
      this.y_speed = -ballSpeed;
      this.x_speed += paddle1.x_speed / 2;
      this.y += this.y_speed;
    }
  } else if (
    top_y < paddle2.y + paddle2.height &&
    bottom_y > paddle2.y &&
    top_x < paddle2.x + paddle2.width &&
    bottom_x > paddle2.x
  ) {
    this.y_speed = ballSpeed;
    this.x_speed += paddle2.x_speed / 2;
    this.y += this.y_speed;
  }
};

const player = new Player();
const computer = new Computer();
const ball = new Ball(ballPositionX, ballPositionY);

function render() {
  player.render();
  computer.render();
  ball.render();
}

function update() {
  player.update();
  computer.update(ball);
  ball.update(player.paddle, computer.paddle);
}

function step() {
  update();
  render();
  // app.ticker.update(step);
}

document.body.appendChild(app.view);
app.ticker.add(step);

// Controls

const keysDown = {};

window.addEventListener('keydown', (event) => {
  keysDown[event.keyCode] = true;
});

window.addEventListener('keyup', (event) => {
  delete keysDown[event.keyCode];
});

// resize function for app
function resize() {
  app.view.style.position = 'absolute';
  app.view.style.width = `${window.innerWidth}px`;
  app.view.style.height = `${window.innerHeight}px`;
  app.view.style.display = 'block';
}

window.onresize = () => {
  app.ticker.add(resize);
};

Thanks a lot.

Share this post


Link to post
Share on other sites
Ball.prototype.render = function renderBall() {
  this.graphics = new PIXI.Graphics();
  this.graphics.beginFill(pongColor);
  this.graphics.drawRect(this.x, this.y, this.width, this.height);
  this.graphics.endFill();
  app.stage.addChild(this.graphics);
};

So, every time you want to render the ball, you add one more graphics object to the stage tree. 

You should create that graphics only one time, with fixed x,y=0 or (-width/2, -height/2), then change that graphics position.

Share this post


Link to post
Share on other sites
5 minutes ago, ivan.popelyshev said:

Ball.prototype.render = function renderBall() {
  this.graphics = new PIXI.Graphics();
  this.graphics.beginFill(pongColor);
  this.graphics.drawRect(this.x, this.y, this.width, this.height);
  this.graphics.endFill();
  app.stage.addChild(this.graphics);
};

So, every time you want to render the ball, you add one more graphics object to the stage tree. 

You should create that graphics only one time, with fixed x,y=0 or (-width/2, -height/2), then change that graphics position.

So i should add an update function for each element that just updates the current position, instead of adding multiple instances...i will give it a try. thanks @ivan.popelyshev

Share this post


Link to post
Share on other sites

I decided to rewrite everything ..and managed to get the player movement without the trailing, unfortunately i can't manage to get the ball moving, and i am a bit lost 

 

https://jsfiddle.net/hendrikeng/02utycqq/2/

 

import 'pixi.js';

/* eslint-disable no-undef, func-names, guard-for-in */

/* eslint-disable camelcase,no-restricted-syntax, no-mixed-operators */

// define gamne variables
const appWidth = window.innerWidth;
const appHeight = window.innerHeight;
const paddleWidth = 150;
const paddleHeight = 30;
const ballSize = 15;
const halfBall = ballSize / 2;
const appWidthHalf = appWidth / 2;
const appHeightHalf = appHeight / 2;
const paddleWidthHalf = paddleWidth / 2;
const pongColor = 0x57dfbf;
const bgColor = 0x282625;
const computerPositionX = appWidthHalf - paddleWidthHalf;
const computerPositionY = 50;
const playerPositionX = computerPositionX;
const playerPositionY = appHeight - computerPositionY - paddleHeight;
const ballPositionX = appWidthHalf - halfBall;
const ballPositionY = appHeightHalf - halfBall;
const playerSpeed = 4;
const computerSpeed = 4;
const ballSpeed = 3;

// Setup the ticker and the root stage PIXI.Container.
const app = new PIXI.Application(appWidth, appHeight, {
  antialias: false,
  backgroundColor: bgColor,
  transparent: false,
  resolution: 1,
});

// append app to body
document.body.appendChild(app.view);

// create graphic elements
const player = new PIXI.Graphics();
const computer = new PIXI.Graphics();
const ball = new PIXI.Graphics();

// Player
player
  .beginFill(pongColor)
  .drawRect(playerPositionX, playerPositionY, paddleWidth, paddleHeight)
  .endFill();

// Computer
computer
  .beginFill(pongColor)
  .drawRect(computerPositionX, computerPositionY, paddleWidth, paddleHeight)
  .endFill();

// Ball
ball
  .beginFill(pongColor)
  .drawRect(ballPositionX, ballPositionY, ballSize, ballSize)
  .endFill();

// append childs to app
app.stage.addChild(player);
app.stage.addChild(computer);
app.stage.addChild(ball);

// Player Movement
player.update = function () {
  for (const key in keysDown) {
    const value = Number(key);
    if (value === 37) {
      player.move(-playerSpeed, 0);
    } else if (value === 39) {
      player.move(playerSpeed, 0);
    } else {
      player.move(0, 0);
    }
  }
};

player.move = function (x, y) {
  this.x += x;
  this.y += y;
  this.x_speed = x;
  this.y_speed = y;
  if (this.x < -appWidthHalf + paddleWidthHalf) {
    this.x = -appWidthHalf + paddleWidthHalf;
    this.x_speed = 0;
  } else if (this.x + this.width - paddleWidthHalf > appWidthHalf) {
    this.x = appWidthHalf - this.width + paddleWidthHalf;
    this.x_speed = 0;
  }
};

// computer Movement
computer.update = function (balla) {
  const x_pos = balla.x;
  let diff = -(computer.x + paddleWidthHalf - x_pos);
  if (diff < 0 && diff < -computerSpeed) {
    diff = -ballSize;
  } else if (diff > 0 && diff > computerSpeed) {
    diff = ballSize;
  }
  computer.position.set(diff, 0);
  if (computer.x < 0) {
    computer.x = 0;
  } else if (computer.x + paddleWidthHalf > appWidth) {
    computer.x = appWidth - paddleWidthHalf;
  }
};

// Ball Movement
ball.position.set = function (paddle1, paddle2) {
  this.x += this.x_speed;
  this.y += this.y_speed;
  const top_x = this.x - ballSize;
  const top_y = this.y - ballSize;
  const bottom_x = this.x + ballSize;
  const bottom_y = this.y + ballSize;

  if (this.x - ballSize < 0) {
    this.x = ballSize;
    this.x_speed = -this.x_speed;
  } else if (this.x + ballSize > appWidth) {
    this.x = appWidth - ballSize;
    this.x_speed = -this.x_speed;
  }

  if (this.y < 0 || this.y > appHeight) {
    this.x_speed = 0;
    this.y_speed = ballSpeed;
    this.x = appWidthHalf;
    this.y = appHeightHalf;
  }

  if (top_y > appHeightHalf) {
    if (
      top_y < paddle1.y + paddle1.height &&
      bottom_y > paddle1.y &&
      top_x < paddle1.x + paddle1.width &&
      bottom_x > paddle1.x
    ) {
      this.y_speed = -ballSpeed;
      this.x_speed += paddle1.x_speed / 2;
      this.y += this.y_speed;
    }
  } else if (
    top_y < paddle2.y + paddle2.height &&
    bottom_y > paddle2.y &&
    top_x < paddle2.x + paddle2.width &&
    bottom_x > paddle2.x
  ) {
    this.y_speed = ballSpeed;
    this.x_speed += paddle2.x_speed / 2;
    this.y += this.y_speed;
  }
};

// controls
const keysDown = {};

window.addEventListener('keydown', (event) => {
  keysDown[event.keyCode] = true;
});

window.addEventListener('keyup', (event) => {
  delete keysDown[event.keyCode];
});

// update function
function update() {
  player.update();
  computer.update(ball);
  ball.position.set(player, computer);
}

// game loop
app.ticker.add(update);

 

Share this post


Link to post
Share on other sites

you cant just override setter of position "ball.position.set". It just strange, however it might work, I dont see problems in your code. I suggest you to debug it and then if it doesnt work for you, ask in "coding&design"  section, because I think you have more problems with javascript than with pixi. Please read that book: http://shop.oreilly.com/product/9780596805531.do

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.