Install quixotic.min.js
In a module js file, import QuixoticEngine
which is exported as default
const game = {
create: {
display: {
canvas: document.querySelector("#canvas")
},
homeURL: "/js/quixotic"
},
style: {
backgroundColor: "#111122"
},
world: {},
engine: {
frameRate: 1000/60,
update: function(deltaTime, engine){},
render: function(display){}
},
setup: function(engine, display, controller, world){}
};
game.create
takes care of creating the game, it requirs 2 values:
1: display(Object), the display object requirs a canvas key, which value should be a canvas element.
| key | type | value | default | | ---------- |: ---- | :----------------------------------------------------- | :------ | | width | Number | A number for the canvas width . | min of width and height | | height | Number | A number for the canvas height. | min of width and height | | zAxis | Number | A number for where the camera z coordinates will be. | 6 |
2: homeURL(String), a url to where the index.js of the engine is located.
game.style
takes care of styling the canvas, style object must be initialized but may be empty.
key | type | value |
---|---|---|
stroke | Object | See table below |
backgroundColor | Quixotic.color | A quixotic color for the stroke |
backgroundImage | String | Link to image location |
key | type | value | required |
---|---|---|---|
width | Number | Stroke width | true |
color | Quixotic.color | A quixotic color for the stroke | true |
game.engine
is where the fun stuff are, it requirs 3 values:
1: frameRate(Number), the game frameRate. The game will update as fast as it can, but will only render under the frameRate.
2: Update(Function), the upate function. This function will get called as fast as possible. Use this to update non-engine related stuff as you wish. All Quixotic.gameEntities
will get updated automatically.
3: Render(Function), the render function. This function will get called as fast as possible under the frameRate. Use this to render non-engine related stuff as you wish. All Quixotic.gameEntities
will get rendered automatically.
argument | type | value |
---|---|---|
deltaTime | Number | time passed in meli-seconds |
engine | Engine | The engine instance |
| argument | type | value | | ----------|: ----- | :--------------------------------- | | display | Display | The Display instance used by engine |
game.setup
is where you setup your game, 4 arguments are being passed down to this function:
engine, display, controller, world
| argument | type | value | | -------------|: ---- : | :----------------------------- | | engine | Engine | The engine instance | | display | Display | The Display instance used by engine | | controller | Controller | The Controller instance used by engine | | world | Object | An Object containing the created world |
Now that we created the initial object, now we actually create the engine.
Quixotic.create(game.create)
.then(engine => {
engine.setup({
style: game.style,
world: game.world,
engine:game.engine,
setup: game.setup,
});
});
There is no game with no objects, so lets create a player.
game.world.objects = [
{
name: "player",
}
];
Now technically the player object have been created, but it's invisible. Lets fill it with a color.
You might wanna extend the Entity class for 2 reasons, collision detection or having custom methods.
import {Entity} from "/js/quixotic/index.js"
class Player extends Entity {
constructor(){
super();
//Must always call super
}
}
game.world = {
classes: {
Player
},
objects: [
{
name: "player",
class: "Player"
}
],
};
We color objects in our setup function.
game.setup = function(engine, display, controller, world){
world.objects.player.fill("#ff00000")
};
We attach images to objects also in the setup function.
game.setup = function(engine, display, controller, world){
//world.objects.player.fill("#ff00000")
const marioTexture = display.createTexture("mario.png");
world.objects.player.attachImage(marioTexture);
};
You can use the same texture for as many objects as you like, you can also create copies of the texture for different transformations.
import {Texture} from "/quixotic/index.js"
//...
game.setup = function(engine, display, controller, world){
const marioTexture = display.createTexture("mario.png");
const textureCopy = Texture.from(marioTexture)
world.objects.player.attachImage(textureCopy);
};
Say you want to create 500 trees, creating each one manually is gonna be a living hell. You can simply set the array
key to true.
const treeObjects = {
name: "trees",
array: true,
amount: 10,
};
The coordinate system in the engine is like looking at a graph, (0, 0) will be the center of the screen, (1, 1) being towrd top right, (-1, -1) being bottom left.
set:playerObject.position = {
type: "set",
position: [-5, 5]
};
random:
playerObject.position = {
type: "random",
rangeX: [-30, 30],
rangeY: [-30, 30]
};
treeObjects.position = {
type: "set",
positions: [ [-10,10], [-15,10], [-5,10], [0,10], [5,10], [10,10], [15,10], [20,10], [25,10], [30,10]]
};
name | description | arguments | passed arguments |
---|---|---|---|
attachKeyDown | Attach a function to a key, gets called when that key is pressed down | Key name(String), function(Function) | None |
attachKeyUp | Attach a function to a key, gets called when that key is realased | Key name(String), function(Function) | None |
attachMouseButton | Attach a function to a button, gets called when that button is pressed | X, Y, W, H(Number), function(Function) | x(Number), y(Number) |
detachKeyUp | detach key up | Key name | |
detachKeyDown | detach key down | Key name |
game.setup = function(engine, display, controller, world){
const player = world.objects.player;
const marioTexture = display.createTexture("mario.png");
const lugiTexture = display.createTexture("lugi.png");
player.attachImage(marioTexture);
controller.attachKeyUp("1", function(){
player.attachImage(marioTexture);
});
controller.attachKeyUp("2", function(){
player.attachImage(lugiTexture);
});
controller.attachKeyDown(" ", function(){ //space
player.accelerate(0, 20); //make mario move up
});
const canvas = display.canvas;
controller.attachMouseButton(0, 0, canvas.width, canvas.height, function(x, y){ //0, 0 being top left
if(x > canvas.width/2){ //if pressed on the right side of the screen
player.accelerate(20, 0); //move right
} else {
player.accelerate(-20, 0); //else move left
}
});
};
Adding collision to your object was made super simple, first you need to make sure that the objects you create is an instance that extends the Entity class. In this example we would be using the Player
class which we created earlier, and a Tree
class we will create now.Tree
class Player extends Entity {
constructor(){
super();
//Must always call super
}
touchedTree(tree){
tree.remove();
//Entity Method wich will remove the object from the game
}
}
class Tree extends Entity {}
game.world = {
classes: {
Player,
Tree
},
objects: [
{
name: "player",
class: "Player",
collision: {
trees: {
call: "touchedTree",
elastic: true //elastic indicates if it can't go through that object or not
},
}
},
{
name: "trees",
class: "Tree",
array: true,
amount: 20,
position: {
type: "random",
rangeX: [-20, 20],
rangeY: [-20, 20],
}
}
],
};
I know that some people might think that tile maps are an old style, but with this engine the tile map is only used to position the objects, meaning you can move objects as you wish later on.
The way it works is it takes 5 keys
Example using `Player, Stone, Tree` classes: ```js game.world = { objects: [ { name: "stones", type: "class", class: "Stone", array: true, amount: 0, collision: {
player: {
call: "touchedPlayer",
elastic: true
},
}
},
{
name: "trees",
type: "class",
class: "Tree",
array: true,
amount: 0,
collision: {
player: {
call: "touchedPlayer",
elastic: true
},
}
},
{
name: "player",
type: "class",
class: "Player",
},
],
classes: {
Tree,
Stone,
Player,
},
tileMap : {
columns: 5,
tileSize: 5,
startCoords: [0, 0],
values: [
Grass,
Tree,
Stone],
tiles: [
[0, 1], 1, 1, 1, 1,
1, 0, 0, 0, 1,
1, 2, 2, 1, 1,
1, 0, 1, 0, 1,
1, 1, 1, 1, 1,
]
}
}
In this example, the `Tree` class is the same one we been using, and `Stone` class is the exact same but with a different sprite.
As you might have notices the first value of the tiles array is an array as well that is becaue it's a list of objects on the same position in an order from bottom to top. In this case its a tree tile ontop of a grass tile.
![Image of example above](https://github.com/bahaaaldin214/Quixotic-Engine/edit/master/examples/images/tileMap.png "TileMap example")
<h2>Display</h2>
`TODO:`
<h2>Game</h2>
`TODO:`