I have this code on a game I am making:
override public function update():void
{
var pressed:Boolean = false;
if (collide("ground", x, y))
{
trace("COLLISION");
}
if (Input.check(Key.LEFT))
{
xSpeed -= power;
pressed = true;
}
if (Input.check(Key.RIGHT))
{
xSpeed += power;
pressed = true;
}
if (collide("ground", x, y + 1))
{
onTheGround = true;
ySpeed = 0;
if (Input.check(Key.UP))
{
ySpeed -= jumpPower;
}
} else {
ySpeed += gravity;
}
if (Math.abs(xSpeed) < 1 && !pressed)
{
xSpeed = 0;
}
xSpeed *= hFriction;
ySpeed *= vFriction;
adjustXPosition();
adjustYPosition();
}
And then I have some tiles on the map generated by this class:
public class Level1 extends Entity
{
private var _tiles:Tilemap;
private var _grid:Grid;
public function Level1()
{
_tiles = new Tilemap(Assets.SPRITE_TILESET, 1920, 1080, 120, 120);
graphic = _tiles;
layer = 1;
_tiles.setRect(0, 0, 1920 / 120, 1080 / 120, 1);
_tiles.setRect(0, 17, 1920 / 120, 1, 0);
_grid = new Grid(1920, 1080, 120, 120, 0, 0);
mask = _grid;
_grid.setRect(0, 17, 1920 / 120, 1, true);
type = "ground";
}
}
But when the player touches on the ground, no collision is detected! And the player just falls through it! What is it that is wrong? I thought "type" was gonna make it work, but I guess I was wrong..
if (collide("ground", x, y))
i think you shouldn't use "x,y" instead of "0,0" because this parameters aren't for position of collision, if i remember right, it is for offset of collision as optional.
so, when you use x,y for this parameters, it may be meaning x+x,y+y as position.
so here,
(collide("ground", x, y + 1))
you should use
(collide("ground", 0, 1))
i'm not sure about that, but you can try this.
Did you give your player a proper HitBox? It looks like your Level1 class is set up properly, but you didn't include the code for your player's hitbox.
You can give your player a basic hitbox like so:
player.setHitbox(64, 64, 0, 0);
Related
I begin to animate a blue square in HTML5 inside a canvas tag, I add another red square as enemy; but when I move the blue square, the red one disappear and the blue one turn red. In fact, I want to keep the color of the blue square and I don't want the red one disappear, how can I solve this problem?
var x = 10;
var y = 360;
var xEnnemy = 190;
var yEnnemy = 10;
var v = 4;
var width = 400;
var height = 400;
var can = document.getElementById("can");
var ctx = can.getContext("2d");
ctx.fillStyle = "skyblue";
ctx.fillRect(x, y, 40, 40);
ctx.fillStyle = "red";
ctx.fillRect(xEnnemy, yEnnemy, 20, 20);
window.onkeydown = function direc(e) {
//Move left
if (e.keyCode == 37 && x > 0) {
x -= v;
}
//Move up
if (e.keyCode == 38 && y > 0) {
y -= v;
}
//Move right
if (e.keyCode == 39 && x < (width - 40)) {
x += v;
}
//Move down
if (e.keyCode == 40 && y < (height - 40)) {
y += v;
}
ctx.clearRect(0, 0, width, height);
ctx.fillRect(x, y, 40, 40);
}
function ennemy() {
ctx.fillStyle = "red";
ctx.fillRect(xEnnemy, yEnnemy, 40, 40);
}
#can {
border: 1px solid black;
}
<html>
<body>
<canvas id="can" width="400" height="400"></canvas>
</body>
</html>
Using ctx.clearRect(0, 0, width, height); clears the entire scene so you need to redraw everything.
You probably want to define a drawPlayer function similar to ennemy like:
function drawPlayer(){
ctx.fillStyle = "skyblue";
ctx.fillRect(x, y, 40, 40);
}
Then, after updating the game state you'd call:
ctx.clearRect(0, 0, width, height);
drawPlayer();
ennemy();
This will update the canvas with the new positions and with the appropriate colors.
Look at what you are doing in the: function direc(e) {
ctx.clearRect(0, 0, width, height);
ctx.fillRect(x, y, 40, 40);
That is effectively wiping the canvas and only drawing one rectangle...
Here is what I would do
var player = {x:10, y:100, v: 4}
var enemy = {x:190, y:10};
var can = document.getElementById("can");
var ctx = can.getContext("2d");
window.onkeydown = function direc(e) {
if (e.keyCode == 37 && player.x > 0)
player.x -= player.v; // Move left
if (e.keyCode == 38 && player.y > 0)
player.y -= player.v; // Move up
if (e.keyCode == 39 && player.x < (can.width - 40))
player.x += player.v; // Move right
if (e.keyCode == 40 && player.y < (can.height - 40))
player.y += player.v; // Move down
draw()
}
function draw() {
ctx.clearRect(0, 0, can.width, can.height);
ctx.fillStyle = "skyblue";
ctx.fillRect(player.x, player.y, 40, 40);
ctx.fillStyle = "red";
ctx.fillRect(enemy.x, enemy.y , 20, 20);
}
draw()
#can {
border: 1px solid black;
}
<canvas id="can" width="400" height="160"></canvas>
I consolidated all the drawing in one location function draw() any time we need to draw we can call that, at the moment you only have one event: onkeydown but as your game gets more complex very likely you will have more and they all will require drawing, we just call the same function.
Also I introduced objects player = {x:10, y:100, v: 4} that keep all the properties of the player in one object, that makes the code easier to read
I am trying to improve my html5 game that I am creating, I am trying to put player object movement into the game like so :
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
theplayer = function(width, height, color, x, y)
{
this.width = width;
this.height = height;
this.color = color;
this.speedx = 0;
this.speedy = 0;
this.x = x;
this.y = y;
this.update=function()
{
context.fillStyle = color;
context.fillRect(this.x,this.y,this.width,this.height);
}
this.newpos=function()
{
this.x += this.speedx;
this.y += this.speedy;
}
}
var theplayer = new theplayer(30, 30, "red", 10, 120);
function clearboard()
{
context.clearRect(0,0,canvas.width,canvas.height);
}
function movement()
{
document.addEventListener("keydown",keyPressed, false);
document.addEventListener("keyup",keyLifted, false);
}
function keyPressed(event)
{
var keyPressed = String.fromCharCode(event.keyCode);
if (keyPressed == "W")
{
theplayer.speedx += 1;
}
else if (keyPressed == "D")
{
theplayer.speedy += 1;
}
else if (keyPressed == "S")
{
theplayer.speedx -= 1;
}
else if (keyPressed == "A")
{
theplayer.speedy -= 1;
}
}
var rungame = setInterval(function()
{
clearboard();
theplayer.newpos();
theplayer.update();
}, 20);
The program should make the player control the player object with the WASD keys but I am unable to make the change of X and Y coordinates apply to 'theplayer' object into the 'newpos' function. How can I solve the problem and is there anyway to put multiple key stroke presses of the WASD keys ?
Hello first time asking a question and I would appreciate any help as I code just for fun. I'm making a simple game in canvas and need help to adjust the hitbox on two objects. I read several other threads that touch on the subject but couldn't find one that answers my question.
Example of what is happening
As seen from the image the hitbox of the smiley face extends beyond the actual image that is drawn. The actual image in the game will be more complex than a smiley face. However using the bounding box method does not account for what the user does not see so on screen, as the images do not look like they are colliding but in reality they are. I thought of trying to clip the image by drawing a triangle within the hitbox and then doing some calculations based on the area. This is what I came up with so far.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var player = {
x: 0,
y: 0,
width: 100,
height: 100
}
var obstacle = {
x: 150,
y: 100,
width: 100,
height: 100
};
document.addEventListener("keydown", keyDownHandler);
function keyDownHandler(e) {
ctx.clearRect(0,0,canvas.width,canvas.height);
if(e.keyCode === 37) {
player.x -= 10;
}
else if(e.keyCode === 38) {
player.y -= 10;
}
else if(e.keyCode === 39) {
player.x += 10;
}
else if(e.keyCode === 40) {
player.y += 10;
}
function drawTriangle(){
ctx.beginPath();
ctx.moveTo(player.x+player.width,player.y+player.height-40);
ctx.lineTo(player.x+player.width-40,player.y+player.height);
ctx.lineTo(player.x+player.width,player.y+player.height);
ctx.closePath();
ctx.fillStyle="orange";
ctx.fill();
}
function drawObstacle(){
ctx.beginPath();
ctx.fillRect(obstacle.x,obstacle.y,obstacle.width,obstacle.height);
ctx.closePath();
}
function colorChange(){
var color = "black";
var triArea = (player.y+player.height-40)*(player.x+player.width-40)/2;
if(player.x+player.width >= obstacle.x &&
player.x <= obstacle.x+obstacle.width &&
player.y <= obstacle.y+obstacle.height &&
player.y+player.height >= obstacle.y){
if(triArea <= 5500 && triArea != 5250){
color = "red";
}
else {
color = "green";
}
document.getElementById("playerArea").innerHTML = ((player.x+player.width)*(player.y+player.height));
document.getElementById("triangleArea").innerHTML = triArea;
}
else{
color = "black";
}
ctx.fillStyle = color;
}
ctx.strokeRect(player.x,player.y,player.width,player.height);
colorChange();
drawObstacle();
ctx.closePath();
drawTriangle();
}
https://codepen.io/brucelin82/pen/aqQLxW?editors=1010
The obstacle will change to red if a collision has occurred but not past the triangle. Once the collision extends beyond the triangle the obstacle will turn to green. The code is still a work in progress but I was just wondering if I'm on the right track or if there is an easier method to account for the empty space within the image. Thank you in advance for any direction you can give me.
I have recently been making a game in dart. In the game, the user controls a space ship sprite with the W, A, S and D keys. These will make the sprite move UP. Left, Right and Down respectively. Space will make a square that represents a projectile, missile bullet etc. move at great speed in the direction the ship is facing.
I have a very bad system that works:
(FOR HANDLING KEY PRESS)
bool drawBull = false;
void handleKeyboard(KeyboardEvent event) {
kevent = event.keyCode;
if (kevent == KeyCode.W || kevent == KeyCode.UP){
direction = 'up';
window.console.log('w / up');
}
else if (kevent == KeyCode.A || kevent == KeyCode.LEFT){
direction = 'left';
window.console.log('a / left');
}
else if (kevent == KeyCode.S || kevent == KeyCode.DOWN){
direction = 'down';
window.console.log('s / down');
}
else if (kevent == KeyCode.D || kevent == KeyCode.RIGHT){
direction = 'right';
window.console.log('d / right');
}
else if (kevent == KeyCode.SPACE) {
shotX = lastX; shotY = lastY;
if (direction == 'right') { shotX = shotX + 400; }
if (direction == 'down') { shotY = shotY + 400; }
drawBull = true;
window.console.log('space');
} else {
return null;
}
}
And the draw function itself:
void draw() {
canvas.width = canvas.width;
switch (direction) {
case 'up':
lastY = lastY - 3;
context.drawImage(shipU, lastX, lastY);
if (drawBull) { shotY = shotY - 30; context.fillRect(lastX + 240, shotY, 20, 20); }
break;
case 'left':
lastX = lastX - 3;
context.drawImage(shipL, lastX, lastY);
if (drawBull) { shotX = shotX - 30; context.fillRect(shotX, lastY + 240, 20, 20); }
break;
case 'down':
lastY = lastY + 3;
context.drawImage(shipD, lastX, lastY);
if (drawBull) { shotY = shotY + 30; context.fillRect(lastX + 240, shotY, 20, 20); }
break;
case 'right':
lastX = lastX + 3;
context.drawImage(shipR, lastX, lastY);
if (drawBull) { shotX = shotX + 30; context.fillRect(shotX, lastY + 240, 20, 20); }
break;
default:
return null;
}
}
As you can see, this is a long untidy and tedious method. However, despite all my brain racking I can't think of a system that avoids these many if/switch statements and the idea of writing out the draw image and shooting code for each one.
My actual game will be heavily object orientated of course, so perhaps an object-orientated solution would be helpful.
The code answer given to this question was quite nice, although doesn't fit my needs exactly. So perhaps an adoption of a class like that would work well How to listen to key press repetitively in Dart for games?
Thank you very much for your help!
-Tom W.
Instead of storing directions as strings, you could store the Velocity and/or Rotation of items, and use that for rendering.
You could then store a map of the key vs the velocity change:
var keyHandlers = {
KeyCode.W: new Point(0, 1),
KeyCode.S: new Point(0, -1),
KeyCode.A: new Point(-1, 0),
KeyCode.D: new Point(1, 0),
}
var spritePosition = new Point(0, 0);
void handleKeyboard(KeyboardEvent event) {
if (keyHandlers[event.keyCode])
spritePosition += keyHandlers[event.keyCode];
}
Ultimately, you probably want to actually store a Velocity for the sprite, and use input to increase the velocity; and then "decay" that velocity each frame (to represent gravity/friction, etc.).
If your sprite needs to be rendered at a particular direction, you should store a rotation as well as position and velocity. There's a simple set of slides here that could be useful; and there are also lots of good XNA tutorials out there that will cover building a "GameObject" class to wrap up this state (although XNA is dead, the tutorials are great, and the C# is not a million miles from Dart).
When your ship shoots, you can copy the position and rotation from the ship to the bullet and calculate it's velocity by applying the ships rotation to the starting velocity of your bullet.
There's also a great website by Bob Nystrom at gameprogrammingpatterns.com that I'd recommend reading as you get more into it.
I can scroll the ground left and right, but I can't scroll the ground up and down.
private function scrollStage():void
{
if (lastPosX != lastPosX)
{
canScrollStage = false;
}
else if (lastPosX == lastPosX)
{
canScrollStage = true;
}
if (canScrollStage)
{
if (rightKey)
{
//move background left
//something.x +=(stage.stageWidth * 0.5) - character.x * 2;
}
else if (leftKey)
{
//move backgrounf Roight
}
for (var b:int = 0; b < childrenOnStage; b++)
{
if (getChildAt(b).name == "enemy" || getChildAt(b).name == "enemyRed" || getChildAt(b).name == "knife")
{
getChildAt(b).x += (stage.stageWidth * 0.5) - character.x;
//getChildAt(b).y += - character.y;
}
}
ground.x += (stage.stageWidth * 0.5) - character.x;
//ground.y += (stage.stageHeight * 0.5) - character.y;
//ground.y += (stage.stageHeight) - character.y;
}
else
{
//move the background
}
// do this last, everything moves around object
character.x = stage.stageWidth * 0.5;
lastPosX = character.x;
I have tried doing
character.y = stage.stageHeight * 0.5;
But this just glues the characters y position to the center of the screen.
When the world can scroll I tried implementing this in to my code
//ground.y += (stage.stageHeight * 0.5) - character.y;
but this doesn't really work either.
Can anyone please point me in the same direction or give me tips and advice, I have tried implementing this code
// A 'Camera' is really just a Point within the world we want to center on
// the screen.
var camera:Point = new Point();
// Set the camera coordinates to the char coordinates.
//camera.x = character.x;
camera.y = character.y;
// Adjust the world position on the screen based on the camera position.
// world.x = -camera.x + (stage.stageWidth / 2);
ground.y = -camera.y + (stage.stageHeight / 2);
It does work! But the screen shakes up and down violently
I traced the players y position and it was going up and down
but with out that code the y position stayed the same.
Thank you.
EDIT - GRAVITY
In my main class I have this which stops the player from falling.
for (var c:int = 0; c < childrenOnStage; c++)
{
if (getChildAt(c).name == "player")
{
if (ground.level1Ground.hitTestPoint(getChildAt(c).x + 13, getChildAt(c).y, true) || ground.level1Ground.hitTestPoint(getChildAt(c).x - 13, getChildAt(c).y, true))
{ //if the boundary collides with the player or enemy
while (ground.level1Ground.hitTestPoint(getChildAt(c).x + 13, getChildAt(c).y, true) || ground.level1Ground.hitTestPoint(getChildAt(c).x - 13, getChildAt(c).y, true))
{
OnGround(getChildAt(c)).incrementUp();
//bump up the object until it isn't hitting the boundary;
if (ground.level1Ground.hitTestPoint(getChildAt(c).x + 13, getChildAt(c).y, true) || ground.level1Ground.hitTestPoint(getChildAt(c).x - 13, getChildAt(c).y, true))
{
// do nothing
//touchingGround = false;
}
else
{ // once it isn't hitting the boundary, do this function for keeping the object on the boundary
OnGround(getChildAt(c)).keepOnGround();
touchingGround = true;
}
}
// ends while ( _boundaries.hitTestPoint ( getChildAt(c).x , getChildAt(c).y, true) ) {;
}
else
{
// ends if ( _boundaries.hitTestPoint ( getChildAt(c).x , getChildAt(c).y, true) )
touchingGround = false;
}
this is the the onGround class.
public class OnGround extends MovieClip
{
protected var grav:int = 1;
protected var charIsrunning:Boolean;
protected var isDefending:Boolean;
protected var isJumping:Boolean;
public function OnGround()
{
addEventListener(Event.ADDED_TO_STAGE, init)
charIsrunning = false;
isDefending = false;
//gotoAndStsop("jump");
}
private function init(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
grav = 1;
addEventListener(Event.ENTER_FRAME, fall);
}
private function fall(e:Event):void
{
grav ++;
if (grav > 15)
{
grav = 10;
}
this.y += grav;
}
public function incrementUp():void
{
//this.y -= 0.1;
}
public function keepOnGround():void
{
grav = 0;
positionOnLand();
}
public function positionOnLand():void
{
//overide
}
}
}
I fear that camera.y can't keep up with character.y or character.y changes despite the code telling the game "Stop falling, your y axis is being invcremented."
Glancing at the code, I'll throw this out as a possible answer. It would seem that the camera's Y position changes with even the slightest change in the player's Y position. (Why that isn't happening on X beats me.)
The first thing that comes to mind is that we need to make the camera a lot less sensitive. We can do this by forcing the function to use an estimation of the position. (By the way, this will only work as long as the character is NOT glued to the center of the screen.)
Since I don't have the whole project, I can't test this. If this line doesn't fix the problem, play with the concept.
camera.y = Math.round(character.y);
Essentially, I'd be forcing the camera to work with whole Y values, not decimal values. That could theoretically cut down on some of the shaking.
If helps some, but not enough, we could implement this to make it go based off of ten pixels, not one. Again, untested (math could be a little off), but you get the idea.
camera.y = Math.round(character.y/10) * 10;
The one theoretical downside of that second method is that the screen will jump when it readjusts. You may need to do some additional coding to make it smooth.
This is a potential answer, whaT I have done is changed this block of code to...
/*if (ground.level1Ground.hitTestPoint(getChildAt(c).x + 13, getChildAt(c).y, true) || ground.level1Ground.hitTestPoint(getChildAt(c).x - 13, getChildAt(c).y, true))
{ //if the boundary collides with the player or enemy
getChildAt(c).y --;
while (ground.level1Ground.hitTestPoint(getChildAt(c).x + 13, getChildAt(c).y, true) || ground.level1Ground.hitTestPoint(getChildAt(c).x - 13, getChildAt(c).y, true))
{
//bump up the object until it isn't hitting the boundary;
if (ground.level1Ground.hitTestPoint(getChildAt(c).x + 13, getChildAt(c).y, true) || ground.level1Ground.hitTestPoint(getChildAt(c).x - 13, getChildAt(c).y, true))
{
// do nothing
//touchingGround = false;
}
else
{ // once it isn't hitting the boundary, do this function for keeping the object on the boundary
OnGround(getChildAt(c)).keepOnGround();
touchingGround = true;
// getChildAt(c).y --;
}
}
// ends while ( _boundaries.hitTestPoint ( getChildAt(c).x , getChildAt(c).y, true) ) {;
}
else
{
// ends if ( _boundaries.hitTestPoint ( getChildAt(c).x , getChildAt(c).y, true) )
touchingGround = false;
}
*/
This! I removed the while!
if (ground.level1Ground.hitTestPoint(getChildAt(c).x + 13, getChildAt(c).y, true) || ground.level1Ground.hitTestPoint(getChildAt(c).x - 13, getChildAt(c).y, true))
{
getChildAt(c).y --;
//OnGround(getChildAt(c)).incrementUp();
OnGround(getChildAt(c)).keepOnGround();
touchingGround = true;
}
else
{
touchingGround = false;
}
I can't explain why it works, (makes me look like a bad programmer) but it doesn't changed the characters Y position when he is on the ground, thus no more earthquake meaning the dragon can sleep for now.
Credits to JasonMC92 for being there for me each step of the way for helping me realize this is a solution for now.