jonoxia / platform-game Goto Github PK
View Code? Open in Web Editor NEWuntitled HTML 5 side-scroller
untitled HTML 5 side-scroller
As levels get more complex and include assets from more different URLs, they will take longer to load. Need to show player something is happening so they know page isn't frozen.
Implementation-wise, I want basically a basket that I can just throw lots of URLs into, and it will load all of them while updating a progress bar, and then notify the main game loop to start once all assets are loaded.
Not sure exactly how to trigger it, but I'm guessing that the jump function that imparts vertical velocity is somehow being invoked twice before you leave the ground, giving you double vertical velocity.
onGround currently only returns true if the object is resting on a platform. It should also return true if the object is resting on a semiplatform. Otherwise, you can bounce on green platforms but not on brown ones, and it seems you can even revive the double jump bug in certain edge cases.
Create layers in order to have overlapping platforms with consistent behavior. At present, it is random which of two overlapping platforms is drawn on top in play, and the platform select/delete tools in the editor do not consistently identify the top platform as the target of the operation.
sometimes that happens.
by parameterizing I mean, for example:
and so on
Would be really nice to be able to zoom out to see the whole level then zoom back in on the part you want to edit.
Oh, or maybe a minimap that is zoomed out enough to show the whole level, click anywhere on the minimap to position the full-scale screen? That would be cool. Could even replace the (kind of awkward) scroll tool.
Currently there is no way to draw a platform longer than one screen. Zooming out would make that possible.
(As properties of the whole level, not as individual level objects. TheWorld shouldn't draw anything at start location, so the editor will need to draw something there to indicate it.)
...I've just always wanted to file a bug that said that.
Most side-scrollers have a control scheme where holding down the jump button gives you maximum height, while tapping it quickly gives you little hops. Right now there is no way to do little hops in this game. It would be nice.
To implement controls like this, though, means being able to continue accelerating upwards for some time after leaving the ground, as long as the space bar is still being held down, which is contrary to how the jump code currently works. So that will need to change.
For slopes/hills. How should the player interact with these, physics-wise? If you jump do you jump up or perpendicular to the surface? Do you go slower when running up them, faster when running down them, or both? If you slam into one at an angle then what happens to your velocity vector: do you skid?
Level editor should have a canvas where you can click and drag around to create/move/remove blocks.
Block positions get stored to level entity in database.
When you start playing, you pick a level from the ones available.
Each level is owned by the user who created it. Only that user can edit it.
Eventually levels should have high scores as well as a "how fun was this level? how hard was this level?" rating system.
later: monster API
Try requestAnimationFrame?
Either adjust it dynamically to screen size, or just make it small.
I think part of the reason the game feels so hard to control right now is that you don't have any more traction on the ground than you do when you're in the air. Should be easier to change direction when something solid is under your feet. Maybe add the ground friction (which should be a property of the platform!) to the x-axis acceleration when there's ground under the player?
Power-ups needs to be able to include:
so this needs to be quite a flexible API.
DefinePowerUp( {
name: "Wall Jump",
sprite: "http://some/site/walljump.png",
expires: false,
onCollect: function(powerup, player) {
player.addToStatusBar(powerup.sprite);
// player.addListener API needs some work -- what will fire events and what will they be called?
// several ways to implement something like this - what's a listener, what's state on an object,
// and what's an if-then check?
player.when("touchwall", function(player, event, world) {
// event tells us e.g. which side the wall was on
if (player.touchingFloor() == false) {
player.wallJumpStance = true;
player.setSprite("grab");
// todo set it to be left wall jump stance or right wall jump stance?
// todo require player to be holding button towards wall?
}
});
player.when("leavewall", function(player, event, world) {
player.wallJumpStance = false;
});
player.when("touchfloor", function(player, event, world) {
player.wallJumpStance = false;
player.setSprite(); // normal
});
player.when("jump-button", function(player, event, world) {
if (player.wallJumpStance == true) {
player.addVelocity(awayFromWall * 30, -30);
}
});
// TODO when and how can these event listeners be unregistered?
}
});
DefinePowerUp( {
name: "Invincibility",
sprite: "http://some/site/invincible.png",
expires: 10, // seconds
onCollect: function(powerup, player) {
// how does the asset loader know to cache this bgm file?
setBackgroundMusic("http://some/site/invincible-music.mid");
player.when("touchmonster", function(player, event, world) {
event.monster.kill();
event.preventDefault(); //????
});
player.flash(); // ????
},
onExpire: function(powerup, player) {
setBackgroundMusic(); // normal //????
player.stopFlashing(); // ????
player.unregister("touchmonster"); // ????
}
});
DefinePowerUp( {
name: "Rocket Launcher",
sprite: "",
expires: false,
ammo: 3, // presence of ammo property automatically adds ammo meter to status bar
// TODO do new special weapons just replace old ones or is there a switch-weapon button?
onCollect: function(powerup, player) {
player.when("fire-button", function(player, event, world) {
if (powerup.ammo == 0) {
return;
}
powerup.ammo -= 1; // triggers a setter which updates meter?
// TODO how about letting player aim projectiles?
player.launchProjectile({
sprite: "",// actually sprite sheet with left-and-right facing
gravity: false,
onContactPlayer: function(projectile, player) {
projectile.explode();
},
onContactMonster: function(projectile, monster) {
projectile.explode();
},
onContactWall: function(projectile, world) {
projectile.explode();
},
onLaunch: function(projectile, world) {
projectile.explode = function(){
world.allWithinDistance(projectile, 45, function(entity) {
entity.damage(3);
});
projectile.stop();
};
}
}, player.facing * 40, 0);
});
}
});
// events: Jump, touchfloor, getpowerup, touchmonster, touchobstacle, touchwall, touchcieling
// leavefloor, leavewall
// conditions: ledgeUnderneath, buttonPressed,
player should be able to take more than one hit before dying.
That means we need a heart meter on the screen, we need a damage() method for the player, and we need some kind of knockback/mercy invincibility to happen when you get hit by a monster.
Reported by Satyreyes:
" A box less than three pixels thick cannot be selected or deleted in the editor. (Alternatively: a box less than three pixels thick can be created in the editor.)"
I think there should be a minimum size on boxes anyway.
Imagining my ideal API for defining a new monster behavior, it might look something like this:
DefineMonster( {
name: "Spider", // to display in the monster selector interface in the level designer
sprites: "http://some/sitespider.png",
speed: 5,
jump: 0,
health: 1,
// size = 1 block by 1 block unless overridden
// initial x, y = defined by level editor
onContactPlayer: function(monster, player, contactDirection) {
// player object has full API for doing crazy stuff
if (contactDirection == "top") { // player landed on top of me
monster.damage(1);
player.bounce();
} else {
player.damage(2);
player.knockBack(10);
}
},
onMove: function(monster, world, tick) {
if ( tick % 20 == 0) { // every 20 ticks launch a web
monster.launchProjectile({sprite: "web.png",
gravity: true,
onContactPlayer: function(projectile, player) {
player.applyCondition("speed", -2, 10); // speed -2 for 10 secs
},
onContactMonster: function(projectile, monster) {
// don't do anything
},
onContactWall: function(projectile, world) {
projectile.stop();
}}
monster.facingDirection * 40, -20); // initial vx, vy
}
if (world.ledgeUnderneath(monster)) {
monster.reverseFacing();
} else if (world.wallInFrontOf(monster)) {
monster.reverseFacing();
} else {
monster.walkForward();
}
}
});
Pointed out by googleshng and satyreyes in this comment thread: http://www.evilbrainjono.net/blog?showcomments=true#1028c
There is a PointlessTrinket class, and it counts how many you collect, but this is not displayed or stored anywhere.
Would be nice to keep track of how many trinkets (out of how many maximum possible trinkets?) were collected each time a player beats a level -- this can be shown on the scoreboard too, so there are two reasons to replay a level - to go for better speed or to go for more trinkets.
The tool for placing an object with a default box size should just place one per click, rather than making you drag a rectangle to define the box.
Satyreyes says:
"
As a matter of personal preference, I'd suggest, based on my experience with the level editor, that you might want to implement a new kind of platform that is permeable from below and from the sides but not from above. NES platformers from Mega Man to Mario 3 found this useful, but until I used your level editor I never realized why: these platforms make level design more flexible by keeping platforms from getting in the way of earlier jumps. For instance, I can't make a level in your editor that makes the player undertake a series of alternating jumps to the left and to the right up a vertical shaft, because Sticklyman inevitably bangs his head on the higher platforms.
"
Will need to figure out a distinct look for this type of platform.
When a monster kills you, "relod to play again" should be "reload to play again."
The mob appears to spawn with its bottom at the top of the start point defined in the level editor, rather than at the bottom as would be proper.
On death, a button that refreshes the page or restarts the game would feel more natural than a message instructing the player to reload.
Not sure why this happens, but it has happened to several people. I know my login code just says "login rejected" no matter what the error is so I need to look into whether it's a network failure or what. There's no real reason it should be rejecting anyone.
like, right now it goes "crunch" and falls down behind the background, but maybe it should flip upside down and twitch too?
Best times for each level, and who got them, and on what day.
Need a table that's like player--level--duration--day, then we can select from it flexibly to answer questions like "who had the best score" and also "what's my best score for this level?
This is different from the old super-jump bug (bug #2). This one seems to happen when the time between updates is especially long, so maybe that's making weird things happen to the simulation?
Later: Power-up API
In the level editor, you should be able to:
Essentially has to mass-produce tools instead of hard-coding them into HTML.
Needs to be able to pull the list of all creatable objects out of webrunner-world.js somehow... which means we have to be registering the constructors.
Create a rectangle-draggable tool for anything of variable size; a goal-object-style tool for anything of fixed size (powerups and monsters).
Organize all the created tools somehow. It's like, generic stuff at the top:
Start - Goal - Erase - Scroll - Reposition
Then all the ground types:
Block - Platform - etc
Then all the power up types:
Speed Plus - Power Jump - etc
Then all the monster types
Any object in the world other than the start location, goal, or basic block is called an Obstacle
even though some of them may actually be helpful.
Defining one with an imaginary ideal API might look something like this:
DefineObstacle( {
name: "Springboard",
sprite: "http://some/site/springboard.png",
// size = 1 block by 1 block unless overridden
onContactPlayer: function(obstacle, player, contactDirection) {
if (contactDirection == "top") {
player.bounce();
}
if (player.buttonPressed("jump")) {
player.boostSpeed(0, -50);
}
},
onMove: function(obstacle, world, tick) {
// default is to do nothing, but moving platforms could move themselves for instance
}
});
The delete tool in the level editor should be able to delete anything it is pointed at, with the exception of the start and goal locations.
Later: Obstacle API
It should start counting when the level loads and go until you die or reach the goal
When a level is edited, all players' logged scores on that level should reset themselves.
Even if the shrimp has no animation frames, we need shrimp facing left, shrimp facing right, shrimp upside-down because you killed it.
Click in the corner of a platform and drag it = resize.
The level editor would be inaccessible until you had logged in, and if you beat a level you wouldn't be able to save scores. That last part could be really frustrating if you had a great run-through without realizing you were logged out. So maybe if you beat a level while not logged in, it should hang on to your score while prompting you to log in to save it.
put a level row into the levels db table; point the foreign keys of all the level objects at it.
need some UI on the editor page for selecting name of level to load/save, and some UI on the play page to choose the level to save.
Re-use code from listworks.py especially when it's time to give ownership of levels to player records.
Seems to happen especially when you hit the side of a wall near its lower corner while moving downward, as when landing from a jump.
I've already got code for drawing them, just need to make a standard way of storing them in the DB and add a tool to the editor page to allow you to create things like trees and mountains
There are basically five numbers that define how the player controls:
Right now the character feels hard to control; it feel like you have too much momentum. It's hard to change direction and you often overshoot your target on jumps.
So the defaults need to be set a little better: Higher friction and higher acceleration, I think.
But more importantly, the level designer should get to tweak these parameters, so that they can make a low-gravity moon level or a low-friction ice level or whatever they want.
extra weird: create "A Level". Edit it.
When you save changes to the edited version, it creates a new level called "A%20Level" and assigns all the level objects to that one.
Both levels, "A Level" and "A%20Level", show up on the level list! But if you play or edit "A Level", what you actually get is "A%20Level".
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.