/**
* CREDITS!!
* Jam : Music assets
* MisterMike : Link NES sprites for animation reference
*/
namespace SpriteKind {
export let Hitbox = SpriteKind.create()
}
interface Song_Dictionary<T>
{
[key : string] : T;
}
// Game Vars and Counters
let PLAYER_SPEED = 100
let WALK_ANIM_TIME = 200
let RUNNING = false
let player_a_c = 0
let BACKGROUND : Image
let SONGS : Song_Dictionary<music.Playable[]> = {
"overworld" : [music.createSong(assets.song`field`)],
"dungeon" : [music.createSong(assets.song`dungeon`)]
}
let ACTION_KEYS : browserEvents.KeyButton[] = [browserEvents.Z, browserEvents.Space]
// -- Movement calc
let v_a : number[]
let f_x : number
let f_y : number
let mag : number
let anim : animation.Animation
// Camera calc
let bx : number
let by : number
// Screen follows 4:3 ratio
let cam_a_x : number = 64
let cam_a_y : number = 48
let cam_c : number = 40
let move_cam : boolean = false
// Timer calc
let s_time : number
let d_time : number
// Music Logic
let playing_song : boolean = false
// Functions for game
function StartSong(name: string)
{
if (SONGS[name] != null)
{
playing_song = true
timer.background(function(){
while (playing_song)
{
for (let i = 0; i < SONGS[name].length; i++)
{
if (playing_song) SONGS[name][i].play(music.PlaybackMode.UntilDone)
}
}
})
}
}
function BoolToInt(b: boolean) // Converts Boolean to Integer
{
if (b)
{
return 1;
}
return 0;
}
function ShiftCamera(dx: number, dy: number)
{
move_cam = true
/**
* Moves camera using the function f(x)=16ln(x), where x is delta time, until f(x) >= dx or f(y) >= dy
* If either dx or dy is negative, f(x) will be flipped
*/
timer.background(function(){
bx = scene.cameraProperty(CameraProperty.X);
by = scene.cameraProperty(CameraProperty.Y);
s_time = game.runtime()
while (Math.abs(scene.cameraProperty(CameraProperty.X) - bx) < Math.abs(dx) || Math.abs(scene.cameraProperty(CameraProperty.Y) - by) < Math.abs(dy)) {
d_time = (game.runtime() - s_time) / 1000.0
if (dx >= 0 && dy >= 0) {
scene.centerCameraAt(bx + cam_a_x * Math.log(d_time * cam_c + 1) * BoolToInt(dx > 0), by + cam_a_y * Math.log(d_time * cam_c + 1) * BoolToInt(dy > 0))
} else if (dx <= 0 && dy >= 0) {
scene.centerCameraAt(bx - cam_a_x * Math.log(d_time * cam_c + 1) * BoolToInt(dx < 0), by + cam_a_y * Math.log(d_time * cam_c + 1) * BoolToInt(dy > 0))
} else if (dx >= 0 && dy <= 0) {
scene.centerCameraAt(bx + cam_a_x * Math.log(d_time * cam_c + 1) * BoolToInt(dx > 0), by - cam_a_y * Math.log(d_time * cam_c + 1) * BoolToInt(dy < 0))
} else {
scene.centerCameraAt(bx - cam_a_x * Math.log(d_time * cam_c + 1) * BoolToInt(dx < 0), by - cam_a_y * Math.log(d_time * cam_c + 1) * BoolToInt(dy < 0))
}
pause(10)
console.log(scene.cameraProperty(CameraProperty.X) - bx)
}
scene.centerCameraAt(bx + dx, by + dy)
move_cam = false
})
}
function SetBGImage(img: Image)
{
BACKGROUND = img
scene.setBackgroundImage(BACKGROUND)
}
function SetBGColor(color: number)
{
BACKGROUND = image.create(160, 120)
BACKGROUND.fill(color)
scene.setBackgroundImage(BACKGROUND)
}
// Math functions
function GetMagnitude(x: number, y: number)
{
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2))
}
function NormalizeJoystick(speed: number, u: boolean, l: boolean, d: boolean, r: boolean)
{
f_x = BoolToInt(r) - BoolToInt(l)
f_y = BoolToInt(d) - BoolToInt(u)
mag = GetMagnitude(f_x, f_y)
return [speed * (f_x / mag), speed * (f_y / mag)]
}
// Finally I can do some better things
function attachAnim(spr: Sprite, img_anim: Array<Image>, fpms: number, flipped: boolean)
{
anim = animation.createAnimation(player_a_c, fpms)
for (let i = 0; i < img_anim.length; i++)
{
if (flipped)
{
img_anim[i].flipX()
anim.addAnimationFrame(img_anim[i])
}
else
anim.addAnimationFrame(img_anim[i])
}
animation.attachAnimation(spr, anim)
player_a_c++ // Incremeant for the next player animation
}
// Key Pres Logic Simplification
function IsRightPressed()
{
return browserEvents.D.isPressed() || browserEvents.ArrowRight.isPressed()
}
function IsLeftPressed()
{
return browserEvents.A.isPressed() || browserEvents.ArrowLeft.isPressed()
}
function IsUpPressed()
{
return browserEvents.W.isPressed() || browserEvents.ArrowUp.isPressed()
}
function IsDownPressed()
{
return browserEvents.S.isPressed() || browserEvents.ArrowDown.isPressed()
}
function IsActionPressed()
{
for (let i = 0; i < ACTION_KEYS.length; i++)
{
if (ACTION_KEYS[i].isPressed()) return true;
}
return false;
}
function AttachFunctionToKeys(keys: browserEvents.KeyButton[], cb: () => void)
{
for (let i = 0; i < keys.length; i++)
{
keys[i].onEvent(browserEvents.KeyEvent.Pressed, cb)
}
}
// -- Title Screen
SetBGImage(assets.image`title`)
pauseUntil(IsActionPressed)
// -- Game initialization
//scene.setBackgroundImage(assets.image`sky`)
SetBGColor(7)
let usr = sprites.create(assets.image`wiz_front`, SpriteKind.Player)
// Makes a hitbox for the player sprite
let usr_hitbox = sprites.create(assets.image`wiz_hitbox`, SpriteKind.Hitbox)
usr_hitbox.setFlag(SpriteFlag.Invisible, true)
// Sword sprite
let sword = sprites.create(assets.image`sword_up`, SpriteKind.Projectile)
sword.setFlag(SpriteFlag.Invisible, true)
// Sprite variables (will be used with other sprites, likely)
sprites.setDataNumber(usr, "action", 0)
sprites.setDataBoolean(usr, "attacking", false)
attachAnim(usr, [assets.image`wiz_walk_d_1`], 0, false) // Idle down (0)
attachAnim(usr, [assets.image`wiz_walk_r_1`], 0, false)
attachAnim(usr, [assets.image`wiz_walk_r_1`], 0, true)
attachAnim(usr, [assets.image`wiz_walk_u_1`], 0, false)
attachAnim(usr, [ // Down Walk Animation (4)
assets.image`wiz_walk_d_1`,
assets.image`wiz_walk_d_2`
], WALK_ANIM_TIME, false)
attachAnim(usr, [ // Right Walk Animation (5)
assets.image`wiz_walk_r_1`,
assets.image`wiz_walk_r_2`
], WALK_ANIM_TIME, false)
attachAnim(usr, [ // Left Walk Animation (6)
assets.image`wiz_walk_r_1`,
assets.image`wiz_walk_r_2`
], WALK_ANIM_TIME, true)
attachAnim(usr, [ // Up Walk Animation (7)
assets.image`wiz_walk_u_1`,
assets.image`wiz_walk_up_2`
], WALK_ANIM_TIME, false)
/**
* SWORD ANIMATION
*/
attachAnim(usr, [ // Down Swing Animation (8)
img`
. . . e e . 8 8 8 8 8 . . . . .
. . e b e 8 8 8 8 8 8 8 . . . .
. e e b 8 8 1 1 1 1 8 8 8 . . .
e e b b 8 1 1 1 1 1 1 8 8 . b .
e e b b 1 b c b b c 1 1 8 b b .
4 e e b 1 b c b b c b 1 8 b . .
. 4 e e 8 b b c c b b b b . . .
. . 4 e 8 8 b c c b b 6 6 . . .
. . . 4 8 8 8 b b b 6 6 6 6 . .
. . . . e 8 8 8 8 8 6 6 6 6 . .
. . . . 8 e 8 e e 6 6 6 6 8 . .
. . . . 8 8 e e 8 6 6 6 8 8 . .
. . . e e 8 8 e e b b 6 8 8 e .
. . e e e . 8 8 b b b 8 8 e e e
. . . . . . . . b b b . e e e e
. . . . . . . . . . . . . . . .
`,
img`
. . . e e . 8 8 8 8 8 . . . . .
. . e b e 8 8 8 8 8 8 8 . . . .
. e e b 8 8 1 1 1 1 8 8 8 . . .
e e b b 8 1 1 1 1 1 1 8 8 . b .
e e b b 1 b c b b c 1 1 8 b b .
4 e e b 1 b c b b c b 1 8 b . .
. 4 e e 8 b b c c b b b b . . .
. . 4 e 8 8 b c c b b 6 6 . . .
. . . 4 8 8 8 b b b 6 6 6 6 . .
. . . . e 8 8 8 8 8 6 6 6 6 . .
. . . . 8 e 8 e e 6 6 6 6 8 . .
. . . . 8 8 e e 8 6 6 6 8 8 . .
. . . e e 8 8 e e b b 6 8 8 e .
. . e e e . 8 8 b b b 8 8 e e e
. . . . . . . . b b b . e e e e
. . . . . . . . . . . . . . . .
`,
img`
. . . . . 8 8 8 8 8 8 . . . . .
. . . . 8 8 8 8 8 8 8 8 . . . .
. . b . 8 1 1 1 1 1 1 8 . b . .
. . b . 1 1 1 1 1 1 1 1 . b . .
. . b b 1 b c b b c b 1 b b . .
. . b b 1 b c b b c b 1 b b . .
. . . b b b b b b b b b b 6 . .
. . . 8 8 b b c c b b 8 8 6 . .
. e e e e e b b b b 8 8 6 6 6 .
e e 4 e e e e 8 8 8 8 8 b 6 6 .
e 4 4 4 e e 4 e e 8 8 b b b 6 .
e e 4 e e e 4 8 e e e e b b b .
e e 4 e e e 4 e e 8 8 8 8 b . .
e e e e e e 4 8 8 8 8 8 . . . .
. 4 4 4 4 4 e . . e e e . . . .
. . . . e e e . . . . . . . . .
`,
img`
. . . . . 8 8 8 8 8 8 . . . . .
. . . . 8 8 8 8 8 8 8 8 . . . .
. . b . 8 1 1 1 1 1 1 8 . b . .
. . b . 1 1 1 1 1 1 1 1 . b . .
. . b b 1 b c b b c b 1 b b . .
. . b b 1 b c b b c b 1 b b . .
. . . b b b b b b b b b b 6 . .
. . . . 8 b b c c b b 8 6 6 . .
. . e e e e e b b b 8 8 8 b . .
. e e 4 e e e e 8 8 8 8 8 b . .
. e 4 4 4 e e 4 e e 8 8 e . . .
. e e 4 e e e 4 8 e e e 8 . . .
. e e 4 e e e 4 e e 8 8 8 . . .
. e e e e e e 4 8 8 8 e . . . .
. . 4 4 4 4 4 . . e e e . . . .
. . . . . . . . . e e e . . . .
`], 250, false)
attachAnim(usr, [ // Right Swing Animation (9)
img`
. . . . . . . . . . . . . . . .
. . . . . . 8 8 8 8 . . . . . .
. . . . 8 8 8 8 8 1 1 1 1 . . .
. . . 8 8 b 8 8 1 1 1 1 1 1 . .
. . . 8 8 b b 1 1 1 1 1 1 . . .
. . 8 8 8 b b b 1 b b c b . . .
. 8 8 8 1 1 b b 1 b b c b b b .
. 8 . . 1 1 1 b b b b b b . . .
. . . . 8 8 8 8 8 b b b b b . .
. . . 8 8 6 6 6 6 6 6 b b b . .
. . . 8 6 6 6 6 6 6 6 b b . . .
. . 8 8 6 6 6 6 6 6 6 8 . . . .
. 8 8 8 8 6 6 6 8 8 8 e e . . .
e e 8 8 8 8 8 8 e e e e e . . .
e e e 8 8 8 8 8 8 8 8 8 e e . .
. e e e . . . . . . . e e e e .
`,
img`
. . . . . . . . . . . . . . . .
. . . . . . 8 8 8 8 . . . . . .
. . . . 8 8 8 8 8 1 1 1 1 . . .
. . . 8 8 b 8 8 1 1 1 1 1 1 . .
. . . 8 8 b b 1 1 1 1 1 1 . . .
. . 8 8 8 b b b 1 b b c b . . .
. 8 8 8 1 1 b b 1 b b c b b b .
. 8 . . 1 1 1 b b b b b b . . .
. . . . 8 8 8 8 8 b b b b b . .
. . . 8 8 6 6 6 6 6 6 b b b . .
. . . 8 6 6 6 6 6 6 6 b b . . .
. . 8 8 6 6 6 6 6 6 6 8 . . . .
. 8 8 8 8 6 6 6 8 8 8 e e . . .
e e 8 8 8 8 8 8 e e e e e . . .
e e e 8 8 8 8 8 8 8 8 8 e e . .
. e e e . . . . . . . e e e e .
`,
assets.image`wiz_walk_r_2`,
assets.image`wiz_walk_r_1`
], 250, false)
attachAnim(usr, [ // Left Swing Animation (10)
img`
. . . . . . . . . . . . . . . .
. . . . . . 8 8 8 8 . . . . . .
. . . . 8 8 8 8 8 1 1 1 1 . . .
. . . 8 8 b 8 8 1 1 1 1 1 1 . .
. . . 8 8 b b 1 1 1 1 1 1 . . .
. . 8 8 8 b b b 1 b b c b . . .
. 8 8 8 1 1 b b 1 b b c b b b .
. 8 . . 1 1 1 b b b b b b . . .
. . . . 8 8 8 8 8 b b b b b . .
. . . 8 8 6 6 6 6 6 6 b b b . .
. . . 8 6 6 6 6 6 6 6 b b . . .
. . 8 8 6 6 6 6 6 6 6 8 . . . .
. 8 8 8 8 6 6 6 8 8 8 e e . . .
e e 8 8 8 8 8 8 e e e e e . . .
e e e 8 8 8 8 8 8 8 8 8 e e . .
. e e e . . . . . . . e e e e .
`,
img`
. . . . . . . . . . . . . . . .
. . . . . . 8 8 8 8 . . . . . .
. . . . 8 8 8 8 8 1 1 1 1 . . .
. . . 8 8 b 8 8 1 1 1 1 1 1 . .
. . . 8 8 b b 1 1 1 1 1 1 . . .
. . 8 8 8 b b b 1 b b c b . . .
. 8 8 8 1 1 b b 1 b b c b b b .
. 8 . . 1 1 1 b b b b b b . . .
. . . . 8 8 8 8 8 b b b b b . .
. . . 8 8 6 6 6 6 6 6 b b b . .
. . . 8 6 6 6 6 6 6 6 b b . . .
. . 8 8 6 6 6 6 6 6 6 8 . . . .
. 8 8 8 8 6 6 6 8 8 8 e e . . .
e e 8 8 8 8 8 8 e e e e e . . .
e e e 8 8 8 8 8 8 8 8 8 e e . .
. e e e . . . . . . . e e e e .
`,
assets.image`wiz_walk_r_2`,
assets.image`wiz_walk_r_1`
], 250, true)
// attachAnim(usr, [], 250, false)
animation.setAction(usr, 1)
tiles.setCurrentTilemap(assets.tilemap`testing`)
scene.centerCameraAt(80, 60)
StartSong("overworld")
/**
* ATTACKING LOGIC
*/
AttachFunctionToKeys(ACTION_KEYS, function () { // Lets the game know what
if (!sprites.readDataBoolean(usr, "attacking")) {
sprites.setDataBoolean(usr, "attacking", true)
animation.setAction(usr, sprites.readDataNumber(usr, "action"))
pause(50)
animation.setAction(usr, sprites.readDataNumber(usr, "action") + 8) // If it is, play animation
switch (sprites.readDataNumber(usr, "action"))
{
case 0:
sword.setImage(assets.image`sword_down`)
break;
case 1:
sword.setImage(assets.image`sword_right`)
break;
case 2:
sword.setImage(assets.image`sword_left`)
break;
case 3:
sword.setImage(assets.image`sword_up`)
break;
}
pause(1000)
animation.setAction(usr, sprites.readDataNumber(usr, "action"))
sprites.setDataBoolean(usr, "attacking", false)
}
})
// Player Movement & Animation
game.onUpdate(function(){
v_a = NormalizeJoystick(PLAYER_SPEED * BoolToInt(!sprites.readDataBoolean(usr, "attacking")), IsUpPressed(), IsLeftPressed(), IsDownPressed(), IsRightPressed())
usr_hitbox.setVelocity(v_a[0], v_a[1])
usr.setPosition(usr_hitbox.x, usr_hitbox.y)
// Sets a variable for the user sprite, dependant on what key is being pressed
if (!sprites.readDataBoolean(usr, "attacking")) // Do not update facing direction once swinging
{
if (IsLeftPressed()) {
sprites.setDataNumber(usr, "action", 2) // Move Left
} else if (IsRightPressed()) {
sprites.setDataNumber(usr, "action", 1) // Move/Swing Right
}
else if (IsUpPressed()) {
sprites.setDataNumber(usr, "action", 3) // Move up
} else if (IsDownPressed()) {
sprites.setDataNumber(usr, "action", 0) // Move down
}
}
// Checks if the player is actually moving
if (!sprites.readDataBoolean(usr, "attacking") && Math.abs(usr_hitbox.vx) + Math.abs(usr_hitbox.vy) > 0)
animation.setAction(usr, sprites.readDataNumber(usr, "action") + 4) // If it is, play animation
else if (!sprites.readDataBoolean(usr, "attacking"))
animation.setAction(usr, sprites.readDataNumber(usr, "action")) // Otherwise, stop animation
// Camera
if (!move_cam)
{
if (usr_hitbox.top > scene.cameraProperty(CameraProperty.Bottom))
ShiftCamera(0, 114)
else if (usr_hitbox.bottom < scene.cameraProperty(CameraProperty.Top))
ShiftCamera(0, -114)
else if (usr_hitbox.left > scene.cameraProperty(CameraProperty.Right))
ShiftCamera(144, 0)
else if (usr_hitbox.right < scene.cameraProperty(CameraProperty.Left))
ShiftCamera(-144, 0)
}
})
Here’s the whole code, although I don’t believe a lot of this is necessary to understand the problem. I will try the things @xInsqne1 and you said with the “at most every Xms” block, but I might also try doing something else that I might find to work. The idle animation code is included, as an attempted fix at the problem (each animation the character has is offset by four)