http://videobin.org/+70a/8wi.html
You can see what's happening there, and a demo to try it here: http://student.dei.uc.pt/~drgomes/carry/index.html.
So, I'm using Chipmunk JS demos to get an idea of how it works (see https://github.com/josephg/Chipmunk-js). The simple demo starts alright but then things start jumping crazily and I've been trying to figure out this with no luck so far.
var radToDeg = 180 / Math.PI;
function PlayState() {
this.blocks = [];
this.setup = function() {
space.iterations = 100;
space.gravity = new cp.Vect(0, 150);
space.game = this;
this.ground = space.addShape(new cp.SegmentShape(space.staticBody, new cp.v(0, 480), new cp.v(640, 480), 0));
this.ground.setElasticity(0);
this.ground.setFriction(1);
};
this.update = function() {
space.step(this.dt);
for (var i = 0; i < this.blocks.length; i++) {
var block = this.blocks[i];
block.sprite.x = block.body.p.x;
block.sprite.y = block.body.p.y;
block.sprite.angle = block.body.a * radToDeg;
}
if (isMouseDown("left")) {
if (this.canAddBlock) {
this.canAddBlock = false;
this.addBlock(mouseX, mouseY);
}
} else {
this.canAddBlock = true;
}
};
this.draw = function() {
clearCanvas();
for (var i = 0; i < this.blocks.length; i++) {
this.blocks[i].sprite.draw();
}
// this.ground.sprite.draw();
};
this.addBlock = function(x, y) {
width = 64;
height = 64;
var newBlock = new Block(x, y, width, height);
newBlock.body = space.addBody(new cp.Body(1, cp.momentForBox(1, width, height)));
newBlock.body.setPos(new cp.v(x, y));
newBlock.shape = space.addShape(new cp.BoxShape(newBlock.body, width, height));
newBlock.shape.setElasticity(0);
newBlock.shape.setFriction(1);
this.blocks.push(newBlock);
};
}
desiredFPS = 60;
switchState(new PlayState());
The source code is pretty straightforward, I have my doubts about the way I'm creating the ground since I can't really tell in what position it actually is. The cubes seem to find it and collide against it though.
The other source file is a little Block class to help me organize things:
Block = (function() {
function constructor(x, y, width, height) {
this.sprite = new Sprite("res/block.png", x, y);
this.width = width;
this.height = height;
}
constructor.prototype = {
update: function() {
}
};
return constructor;
})();
From watching the behavior, I think it is as simple as the sprites and the chipmunk bodies not rotating around the same point. I believe chipmunk rotations are around the center of mass. It looks like the sprites are rotating around the upper left corner. In fact, they may be drawing from that corner too, which explains why they stack funny, and intersect the bottom plane.
I think you need something like this in the update function. (pseudocode):
offset = Vector(-width/2,-height/2)
offset.rotate_by(block.body.a)
block.sprite.x = block.body.p.x + offset.x
block.sprite.y = block.body.p.y + offset.y
I don't know chipmunk at all but playing around with your demo it seems like the Physics isn't right at all (right from the beginning for me). Just a hunch from looking at your code, but it looks to me like you should be setting the dimensions on the Sprite instance in your Block class, rather than on the Block instance itself.
Block = (function() {
function constructor(x, y, width, height) {
this.sprite = new Sprite("res/block.png", x, y);
// Do you mean to set the width and height of the sprite?
this.sprite.width = width;
this.sprite.height = height;
}
constructor.prototype = {
update: function() {
}
};
return constructor;
})();
Related
Ok, so I wrote some code for a JS game. The code itself works, but isn't in proper OOP form. In the class "Enemy" I need to reference variables and a method from the "Player" class. Look in the "Collision" method, where the variables are referenced. Notice that I get the data specifically from the new instance of "Player" called "player" at the end of the script. For OOP, how am I suppose to share information between these two classes?
Thanks!
var Player = function() {
this.x = 15;
this.y = 15;
};
Player.prototype.reset = function() {
this.x = 200; // reset to this
this.y = 320; // reset to this
};
var Enemy = function() {
this.x = 25;
this.y = 30;
};
Enemy.prototype.collision = function() {
if (player.x >= this.x - 35 & player.x <= this.x + 35) { // check column
if (player.y >= this.y - 30 & player.y <= this.y + 30) { // check row
player.reset(); // calls player method "reset"
}
}
};
// Start Game
setEnemies();
var player = new Player();
in javascript functions can take arguments
solution to your problem could be passing instance of Player to method collision
as #Álvaro Touzón mentioned, a good practice would be to use inheritance as Enemy and Player in your code are now basically the same
also, you could read about ES6 classes, which make programming a bit easier, however they still rely on prototype inheritance which makes them just a syntactic sugar
If you want to use OOP, then perhaps this will help you.
Add helper extend function
function extend(current, base) {
for (var key in base) {
if (base.hasOwnProperty(key)) {
current[key] = base[key];
}
}
current.prototype = Object.create(base.prototype);
};
Create class Avatar as #Álvaro Touzón suggested
var Avatar = (function () {
function Avatar (x, y) {
this.x = x;
this.y = y;
}
Avatar.prototype.reset = function() {
return this;
};
Avatar.prototype.collision = function(object) {
if (object.x >= this.x - 35 & object.x <= this.x + 35) { // check column
if (object.y >= this.y - 30 & object.y <= this.y + 30) { // check row
object.reset(); // calls object method "reset"
}
}
};
return Avatar;
}());
Class Player and Enemy
var Player = (function (superClass) {
extend(Player, superClass);
function Player (x, y) {
superClass.apply(this, arguments);
}
Player.prototype.reset = function() {
this.x = 200; // reset to this
this.y = 320; // reset to this
return this;
};
return Player;
}(Avatar));
var Enemy = (function (superClass) {
extend(Enemy, superClass);
function Enemy (x, y) {
superClass.apply(this, arguments);
}
return Enemy;
}(Avatar));
Create Game
var Game = (function () {
Game.prototype.player = new Player(15, 15);
Game.prototype.enemys = [
new Enemy(25, 30),
new Enemy(10, 30),
];
function Game () {
// setup
}
Game.prototype.start = function() {
for (var i = 0; i < array.length; i++){
var enemy = this.enemys[i];
this.player.collision(enemy);
}
return this;
};
return Game;
}());
Use:
var game = new Game();
game.start();
How it works
You have a group of objects - enemies and the object - player, all of them have the ability to calculate collision between each other, because common ancestor. Every time you call the start of the game will be calculated collision. I would add setInterval in game.start for calculated collision but this complicate the code.
I cannot say how you want to run your game but in general, to share data I always believe in making singleton classes and use it in different objects. This way we can do better error handling also. In js, there are no singleton classes as such to say. But you can always make simple js modules like below:
var abc = (function(){
var abc = "someval"; //private variable
var setAbc = function() {
//some logic
}
var getAbc = function() {
//some logic
}
var publicMethod = function {
//some logic
}
return {
setAbc: setAbc,
getAbc: getAbc,
publicMethod: publicMethod
}
})();
It's non of the buisness of the Enemy, to mutate/reset the Player. Nor is it the buisness of the Player, to wich Position it is reset to.
These things should be done by the game in the main game loop, and the collision-method should only determine wether this Element has hit the passed Element.
//manages the bounding-Box / Collisions,
//also pretty much everything related to (basic) rendering, like Assets/Image or DOM-Node, ... but since you've not included that in your code, I can't adapt it.
class Element{
constructor(config){
let {x, y, width, height, hitBoxOffsetX, hitBoxOffsetY} = config || {};
this.x = +x || 0;
this.y = +y || 0;
this._hitBoxOffsetX = +hitBoxOffsetX || 0;
this._hitBoxOffsetY = +hitBoxOffsetY || 0;
this.width = +width || 0;
this.height = +height || 0;
}
//bounding box
get left(){ return this.x + this._hitBoxOffsetX }
get right(){ return this.left + this.width }
get top(){ return this.y + this._hitBoxOffsetY }
get bottom(){ return this.top - this.height }
collision(other){
return this.right > other.left && this.left < other.right &&
this.top > other.bottom && this.bottom < other.top;
}
}
//everything that can somehow be hit, extends Element
class Player extends Element {
constructor(){
super({
hitBoxOffsetX: -35, //hitBox starts 35px to the left of this.x
hitBoxOffsetY: -30, //hitBox starts 30px to the top of this.y
width: 70, //width of the hitBox
height: 60 //height of the hitBox
});
}
}
class Enemy extends Element {
constructor(){
//since I have no idea about the dimensions of these Entities
super();
}
}
//and walls, for example
class Wall extends Element {
constructor(x, y, width, height){
super({
x, y,
width: +width || 20,
height: +height || 20
});
}
}
And the mentioned collision-checking and resetting happens in the main game-loop, but since I don't know how your game-loop looks like, here some pseudocode:
update(){
requestAnimationFrame(update);
//move everything
//collision-checks
//if your player has some sort of weapon, maybe you want to first check
//wether it has "killed" some enemies,
//before checking wether an enemy has hit your player.
var hitEnemy = enemies.find(enemy => enemy.collision(player));
//btw. Bullets would also be "enemies"
if(hitEnemy){
//and you probably don't want to
player.x = currentLevel.playerResetPosition.x;
player.y = currentLevel.playerResetPosition.y;
//destroy hitEnemy
//maybe mark the player as blinking/non-hitable for a few seconds?
}
//render everything
}
as the title said i'm trying to animate on a java canvas but i'm not sure how to add on to the vector class of my objects current position
I've been told to use this:
Bus.prototype.update = function()
{
this.getPosition().add(new Vector(10.0));
}
but it doesn't recognize the .add function and comes up with an error when i use my setInterval function
I'll include my get/set functions aswell just incase
Bus.prototype.getPosition = function() {
return this.mPosition;
};
Bus.prototype.setPosition = function (pPosition) {
this.mPosition = pPosition;
};
I'm pretty new at coding so i apologize if this is very vague or badly written
jsFiddle : https://jsfiddle.net/CanvasCode/41z9o10p/1/
javascript
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var Bear = function(xSet, ySet)
{
this.XPos = xSet;
this.YPos = ySet;
}
Bear.prototype.updatePosition = function(xValue, yValue)
{
this.XPos += xValue;
this.YPos += yValue;
}
var bear = new Bear(0,0);
setInterval( function()
{
ctx.fillStyle = "#000";
ctx.fillRect(0,0,c.width,c.height);
ctx.fillStyle = "#0F0";
ctx.fillRect(bear.XPos, bear.YPos, 50,50);
bear.updatePosition(0.2, 0.4);
} ,1);
Bear is a custom "class". All bear has is a X position and a Y position, the constructor can take in two values which will set the X and Y value. I then add a new method to Bear which is called updatePosition. All updatePosition does it take in two values and add them to the original X position and Y position (you can also provide negative numbers to move the opposite way). Now with our Bear we can create one and then use its updatePosition function and move it.
I am new to Paper.js therefore might this a basic question but I am trying to the the following:
var xpos;
var ypos;
function onMouseMove(event) {
xpos = event.point.x;
ypos = event.point.y;
}
get the current mouseposition and save it as the variables xpos and ypos
function onFrame(event) {
path.segments[1].point.x = path.segments[1].point.x+xpos/10;
path.segments[1].point.y = path.segments[1].point.y+ypos/10;
}
and then use them to update the onFrame animation. But it does not work, how can I update the animation with the new values?
Thanks in advance.
It looks like your code is increasing the position of path.segments[1] every frame. I believe what you want is to subtract a portion of the difference between the segment and mouse positions per frame.
Try this:
var path = new Path.Line((0,0), view.center);
path.strokeColor = "black";
var pos = new Point(0, 0);
function onMouseMove(event) {
pos = event.point;
}
function onFrame(event) {
path.segments[1].point += (pos - path.segments[1].point) / 10;
}
I need to rotate an image inside an canvas..I have googled and saw similar questions in stackoverflow.What i learnt is
I cannot rotate single object inside canvas.
I can rotate only thewhole canvas.
So i need to translate to center of the object and then rotate the
canvas.
I Followed exactly same stuffs , But i am struck at translating to the image center..Below is the code i am using.Here is the jsfiddle http://jsfiddle.net/J6Pfa/1/. This one is rotating the whole canvas regardless image..some one guide me where i am wrong.Thanks
//hero canvas
ball = new Hero();
var ang = 0;
herocanvas = document.createElement("canvas");
herocanvas.width = herocanvas.width = 500;
herocanvas.height = herocanvas.height = 500;
heroctx = herocanvas.getContext('2d');
document.body.appendChild(herocanvas);
var requestAnimFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame;
var imgSprite = new Image();
imgSprite.src = 'http://i.imgur.com/WTgOHGg.png';
imgSprite.addEventListener('load',init,false);
function init()
{
startloop();
}
function startloop()
{
heroctx.save(); //saves the state of canvas
clearherobg() ; // clear canvas
heroctx.translate(ball.drawX, ball.drawY); //let's translate
heroctx.rotate(Math.PI / 180 * (ang += 4));
ball.draw(); // draw image here
heroctx.restore();
requestAnimFrame(startloop);
}
function Hero() {
this.srcX = 0;
this.srcY = 500;
this.drawX = 220;
this.drawY = 200;
this.width = 100;
this.height = 40;
this.speed = 5;
this.isUpKey = false;
this.isRightKey = false;
this.isDownKey = false;
this.isLeftKey = false;
}
Hero.prototype.draw = function () {
heroctx.drawImage(imgSprite,this.srcX,this.srcY,this.width,this.height,this.drawX,this.drawY,this.width,this.height);
};
function clearherobg() {
heroctx.clearRect(0,0,500,500);
}
Those who cannot read full code ..Please check startloop() , thats the main infinite loop..ball.drawX and ball.drawY are the x and y position of image inside canvas
Hero's drawX and drawY need to be updated to new coordinate system of canvas, if u want it to be in the middle of canvas it needs to be 0,0.
Something like this: jsfiddle.net/J6Pfa/3
Hm, i dont exactly understand what you want to achieve, an image moving on the circle path ? or having image in one place, and just rotate it ?
I am making a game and in it I would like to have the ability to use cached canvas's instead of rotating the image every frame. I think I made a function for adding images that makes sense to me, but I am getting an error every frame that tells me that the canvas object is no longer available.
INVALID_STATE_ERR: DOM Exception 11: An attempt was made to use an
object that is not, or is no longer, usable.
You might also need to know that I am using object.set(); to go ahead and add that image to a renderArray. That may be affecting whether the canvas object is still avaliable?
Here is the function that returns a cached canvas, (I took it from a post on this website :D)
rotateAndCache = function(image, angle){
var offscreenCanvas = document.createElement('canvas');
var offscreenCtx = offscreenCanvas.getContext('2d');
var size = Math.max(image.width, image.height);
offscreenCanvas.width = size;
offscreenCanvas.height = size;
offscreenCtx.translate(size/2, size/2);
offscreenCtx.rotate(angle + Math.PI/2);
offscreenCtx.drawImage(image, -(image.width/2), -(image.height/2));
return offscreenCanvas;
}
And here is some more marked up code:
var game = {
render:function(){
//gets called every frame
context.clearRect(0, 0, canvas.width, canvas.height);
for(i = 0; i < game.renderArray.length; i++){
switch(game.renderArray[i].type){
case "image":
context.save();
context.translate(game.renderArray[i].x, game.renderArray[i].y);
context.rotate(Math.PI*game.renderArray[i].rotation/180);
context.translate(-game.renderArray[i].x, -game.renderArray[i].y);
context.drawImage(game.renderArray[i].image, game.renderArray[i].x, game.renderArray[i].y);
context.restore();
break;
}
if(game.renderArray[i].remove == true){
game.renderArray.splice(i,1);
if(i > 1){
i--;
}else{
break;
}
}
}
},
size:function(width, height){
canvas.height = height;
canvas.width = width;
return height + "," + width;
},
renderArray:new Array(),
//initialize the renderArray
image:function(src, angle){
if(angle != undefined){
//if the argument 'angle' was given
this.tmp = new Image();
this.tmp.src = src;
//sets 'this.image' (peach.image) to the canvas. It then should get rendered in the next frame, but apparently it doesn't work...
this.image = rotateAndCache(this.tmp, angle);
}else{
this.image = new Image();
this.image.src = src;
}
this.x = 0;
this.y = 0;
this.rotation = 0;
this.destroy = function(){
this.remove = true;
return "destroyed";
};
this.remove = false;
this.type = "image";
this.set = function(){
game.renderArray.push(this);
}
}
};
var canvas, context, peach;
$(document).ready(function(){
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
//make the variable peach a new game.image with src of meme.jpg and an angle of 20.
peach = new game.image('meme.jpg', 20);
peach.set();
game.size(700,500);
animLoop();
});
If you want, here is this project hosted on my site:
http://keirp.com/zap
There are no errors on your page, at least not anymore or not that I can see.
It's quite possible that the problem is an image that is not done loading. For instance that error will happen if you try to make a canvas pattern out of a not-yet-finished-loading image. Use something like pxloader or your own image loading function to make sure all the images are complete before you start drawing.
Anyway, it's nigh impossible to figure out what was or is happening since your code isn't actually giving any errors (anymore).