initial commit
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
builds/*
 | 
			
		||||
							
								
								
									
										6
									
								
								.vscode/extensions.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.vscode/extensions.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "recommendations": [
 | 
			
		||||
        "sumneko.lua",
 | 
			
		||||
        "jep-a.lua-plus"
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "Lua.runtime.version": "Lua 5.4",
 | 
			
		||||
  "Lua.diagnostics.disable": ["undefined-global", "lowercase-global"],
 | 
			
		||||
  "Lua.diagnostics.globals": ["playdate", "import"],
 | 
			
		||||
  "Lua.runtime.nonstandardSymbol": ["+=", "-=", "*=", "/=", "//=", "%=", "<<=", ">>=", "&=", "|=", "^="],
 | 
			
		||||
  "Lua.workspace.library": ["$PLAYDATE_SDK_PATH/CoreLibs"],
 | 
			
		||||
  "Lua.workspace.preloadFileSize": 1000,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										103
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
{
 | 
			
		||||
	// See https://go.microsoft.com/fwlink/?LinkId=733558
 | 
			
		||||
	// for the documentation about the tasks.json format
 | 
			
		||||
	"version": "2.0.0",
 | 
			
		||||
	"tasks": [
 | 
			
		||||
	  {
 | 
			
		||||
		"label": "Invoke Build and Run script",
 | 
			
		||||
		"type": "shell",
 | 
			
		||||
		"command": "&",
 | 
			
		||||
		"windows": {
 | 
			
		||||
			"args": [
 | 
			
		||||
				"${workspaceFolder}\\Build and Run (Simulator).ps1",
 | 
			
		||||
				"-build",
 | 
			
		||||
				"'${workspaceFolder}\\builds'",
 | 
			
		||||
				"-source",
 | 
			
		||||
				"'${workspaceFolder}\\source'",
 | 
			
		||||
				"-name",
 | 
			
		||||
				"'${workspaceFolderBasename}'"
 | 
			
		||||
			],
 | 
			
		||||
			"options": {
 | 
			
		||||
				"shell": {
 | 
			
		||||
					"executable": "powershell.exe"
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"linux": {
 | 
			
		||||
			"command": "${workspaceFolder}/build_and_run.sh",
 | 
			
		||||
			"args": [
 | 
			
		||||
				"build"
 | 
			
		||||
			]
 | 
			
		||||
		},
 | 
			
		||||
		"presentation": {
 | 
			
		||||
		  "showReuseMessage": false,
 | 
			
		||||
		  "reveal": "always",
 | 
			
		||||
		  "panel": "shared"
 | 
			
		||||
		}
 | 
			
		||||
	  },
 | 
			
		||||
	  {
 | 
			
		||||
		"label": "Invoke Run script",
 | 
			
		||||
		"type": "shell",
 | 
			
		||||
		"command": "&",
 | 
			
		||||
		"windows": {
 | 
			
		||||
			"args": [
 | 
			
		||||
				"${workspaceFolder}\\Build and Run (Simulator).ps1",
 | 
			
		||||
				"-build",
 | 
			
		||||
				"'${workspaceFolder}\\builds'",
 | 
			
		||||
				"-source",
 | 
			
		||||
				"'${workspaceFolder}\\source'",
 | 
			
		||||
				"-name",
 | 
			
		||||
				"'${workspaceFolderBasename}'",
 | 
			
		||||
				"-dontbuild"
 | 
			
		||||
			],
 | 
			
		||||
			"options": {
 | 
			
		||||
				"shell": {
 | 
			
		||||
					"executable": "powershell.exe"
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"linux": {
 | 
			
		||||
			"command": "${workspaceFolder}/build_and_run.sh",
 | 
			
		||||
			"args": [
 | 
			
		||||
				"run"
 | 
			
		||||
			]
 | 
			
		||||
		},
 | 
			
		||||
		"presentation": {
 | 
			
		||||
		  "showReuseMessage": false,
 | 
			
		||||
		  "reveal": "always",
 | 
			
		||||
		  "panel": "shared"
 | 
			
		||||
		}
 | 
			
		||||
	  },
 | 
			
		||||
	  {
 | 
			
		||||
		"label": "Build and Run (Simulator)",
 | 
			
		||||
		"dependsOn": ["Invoke Build and Run script"],
 | 
			
		||||
		"dependsOrder": "sequence",
 | 
			
		||||
		"presentation": {
 | 
			
		||||
		  "showReuseMessage": false,
 | 
			
		||||
		  "reveal": "always",
 | 
			
		||||
		  "panel": "shared"
 | 
			
		||||
		},
 | 
			
		||||
		"problemMatcher": [],
 | 
			
		||||
		"group": {
 | 
			
		||||
		  "kind": "build",
 | 
			
		||||
		  "isDefault": true
 | 
			
		||||
		}
 | 
			
		||||
	  },
 | 
			
		||||
	  {
 | 
			
		||||
		"label": "Run (Simulator)",
 | 
			
		||||
		"dependsOn": ["Invoke Run script"],
 | 
			
		||||
		"dependsOrder": "sequence",
 | 
			
		||||
		"presentation": {
 | 
			
		||||
		  "showReuseMessage": false,
 | 
			
		||||
		  "reveal": "always",
 | 
			
		||||
		  "panel": "shared"
 | 
			
		||||
		},
 | 
			
		||||
		"problemMatcher": [],
 | 
			
		||||
		"group": {
 | 
			
		||||
		  "kind": "test",
 | 
			
		||||
		  "isDefault": true
 | 
			
		||||
		}
 | 
			
		||||
	  }
 | 
			
		||||
	]
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
							
								
								
									
										145
									
								
								build_and_run.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										145
									
								
								build_and_run.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,145 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
export PLAYDATE_SDK_PATH="/home/ut3usw/PlaydateSDK-2.5.0"
 | 
			
		||||
 | 
			
		||||
# Check for color by variable and tput command
 | 
			
		||||
if [[ -z $NOCOLOR && -n $(command -v tput) ]]; then
 | 
			
		||||
    RED=$(tput setaf 1)
 | 
			
		||||
    CYN=$(tput setaf 6)
 | 
			
		||||
    YEL=$(tput setaf 3)
 | 
			
		||||
    RST=$(tput sgr0)
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
function display_help() {
 | 
			
		||||
    printf "%s\n\n" "${0} build|run|-h|--help|"
 | 
			
		||||
    printf "%-16s\n" "build: Builds the project and runs the Simulator"
 | 
			
		||||
    printf "%-16s\n" "run  : Skips building the project and runs the Simulator"
 | 
			
		||||
    printf "\n"
 | 
			
		||||
    printf "%s\n\n" "Set NOCOLOR=1 to disable terminal coloring"
 | 
			
		||||
    exit 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# We don't need fancy flags/operators for two commands
 | 
			
		||||
case $1 in
 | 
			
		||||
    "build")
 | 
			
		||||
        BUILD=1
 | 
			
		||||
        ;;
 | 
			
		||||
    "run")
 | 
			
		||||
        BUILD=0
 | 
			
		||||
        ;;
 | 
			
		||||
    *)
 | 
			
		||||
        display_help
 | 
			
		||||
        exit 1
 | 
			
		||||
        ;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
# Set some paths
 | 
			
		||||
BUILD_DIR="./builds"
 | 
			
		||||
SOURCE_DIR="./source"
 | 
			
		||||
PDX_PATH="${BUILD_DIR}/$(basename $(pwd)).pdx"
 | 
			
		||||
 | 
			
		||||
# Logging functions
 | 
			
		||||
function log() {
 | 
			
		||||
    printf "%s\n" "${CYN}>> $1${RST}"
 | 
			
		||||
}
 | 
			
		||||
function log_warn() {
 | 
			
		||||
    printf "%s\n" "${YEL}>! $1${RST}"
 | 
			
		||||
}
 | 
			
		||||
function log_err() {
 | 
			
		||||
    printf "%s\n  >> %s\n" "${RED}!! ERROR !!" "$1${RST}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function check_pdxinfo() {
 | 
			
		||||
    if [[ -f ./source/pdxinfo ]]; then
 | 
			
		||||
        if grep "com.organization.package" ./source/pdxinfo 2>&1 >/dev/null; then
 | 
			
		||||
            log_warn "PDXINFO NOTICE:"
 | 
			
		||||
            log_warn "Don't forget to change your unique project info in 'source/pdxinfo': 'bundleID', 'name', 'author', 'description'."
 | 
			
		||||
            log_warn "It's critical to change your game bundleID, so there will be no collisions with other games, installed via sideload."
 | 
			
		||||
            log_warn "Read more about pdxinfo here: https://sdk.play.date/Inside%20Playdate.html#pdxinfo"
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function chk_err() {
 | 
			
		||||
    # Check for errors in last process and bail if needed
 | 
			
		||||
    if [[ $? > 0 ]]; then
 | 
			
		||||
        log_err "There was an issue with the previous command; exiting!"
 | 
			
		||||
        exit 1
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function check_close_sim() {
 | 
			
		||||
    # Check if we have 'pidof'
 | 
			
		||||
    PIDOF=$(command -v pidof2)
 | 
			
		||||
 | 
			
		||||
    # Prefer 'pidof'; use ps if not
 | 
			
		||||
    if [[ -n $PIDOF ]]; then
 | 
			
		||||
        SIMPID=$($PIDOF "PlaydateSimulator")
 | 
			
		||||
        if [[ -n $SIMPID ]]; then
 | 
			
		||||
            log "Found existing Simulator, closing..."
 | 
			
		||||
            kill -9 $SIMPID
 | 
			
		||||
            chk_err
 | 
			
		||||
        fi
 | 
			
		||||
    else
 | 
			
		||||
        SIMPID=$(ps aux | grep PlaydateSimulator | grep -v grep | awk '{print $2}')
 | 
			
		||||
        if [[ -n $SIMPID ]]; then
 | 
			
		||||
            log "Found existing Simulator, closing..."
 | 
			
		||||
            kill -9 $SIMPID
 | 
			
		||||
            chk_err
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Create build dir
 | 
			
		||||
function make_build_dir() {
 | 
			
		||||
    if [[ ! -d "${BUILD_DIR}" ]]; then
 | 
			
		||||
        log "Creating build directory..."
 | 
			
		||||
        mkdir -p "${BUILD_DIR}"
 | 
			
		||||
        chk_err
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Clean build dir
 | 
			
		||||
function clean_build_dir() {
 | 
			
		||||
    if [[ -d "${BUILD_DIR}" ]]; then
 | 
			
		||||
        log "Cleaning build directory..."
 | 
			
		||||
        rm -rfv "${BUILD_DIR}/*"
 | 
			
		||||
        chk_err
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Compile the PDX
 | 
			
		||||
function build_pdx() {
 | 
			
		||||
    if [[ $BUILD == 1 ]]; then
 | 
			
		||||
        log "Building PDX with 'pdc'..."
 | 
			
		||||
        $PLAYDATE_SDK_PATH/bin/pdc -sdkpath "${PLAYDATE_SDK_PATH}" "${SOURCE_DIR}" "${PDX_PATH}"
 | 
			
		||||
        chk_err
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Run the PDX with Simulator
 | 
			
		||||
function run_pdx() {
 | 
			
		||||
    if [[ -d "${PDX_PATH}" ]]; then
 | 
			
		||||
        log "Running PDX with Simulator..."
 | 
			
		||||
        $PLAYDATE_SDK_PATH/bin/PlaydateSimulator "${PDX_PATH}"
 | 
			
		||||
    else
 | 
			
		||||
        log_err "PDX doesn't exist! Please 'build' the project first!"
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#### MAIN SCRIPT ####
 | 
			
		||||
if [[ $BUILD == 1 ]]; then
 | 
			
		||||
    log "Attempting a build and run of PDX..."
 | 
			
		||||
    make_build_dir
 | 
			
		||||
    clean_build_dir
 | 
			
		||||
    check_pdxinfo
 | 
			
		||||
    build_pdx
 | 
			
		||||
    check_close_sim
 | 
			
		||||
    run_pdx
 | 
			
		||||
else
 | 
			
		||||
    log "Attempting to run PDX: ${PDX_PATH}..."
 | 
			
		||||
    check_close_sim
 | 
			
		||||
    run_pdx
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								source/audio/hello.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/audio/hello.wav
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/audio/quad.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/audio/quad.wav
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/audio/telemko.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/audio/telemko.wav
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/audio/ukr.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/audio/ukr.wav
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/audio/war.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/audio/war.wav
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										15
									
								
								source/backgroundSprite.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								source/backgroundSprite.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
local pd <const> = playdate
 | 
			
		||||
local gfx <const> = playdate.graphics
 | 
			
		||||
 | 
			
		||||
class("BackGround").extends()
 | 
			
		||||
 | 
			
		||||
function BackGround:init(x, y)
 | 
			
		||||
    gfx.sprite.setBackgroundDrawingCallback(
 | 
			
		||||
		function (x, y, width, height)
 | 
			
		||||
            local groundImage = playdate.graphics.image.new("sprites/bg")
 | 
			
		||||
			gfx.setClipRect(x, y, width, height)
 | 
			
		||||
			groundImage:draw(0,0)
 | 
			
		||||
			gfx.clearClipRect()
 | 
			
		||||
		end
 | 
			
		||||
	)
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								source/font/Mini Sans 2X-table-18-20.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/font/Mini Sans 2X-table-18-20.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 4.4 KiB  | 
							
								
								
									
										265
									
								
								source/font/Mini Sans 2X.fnt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										265
									
								
								source/font/Mini Sans 2X.fnt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,265 @@
 | 
			
		||||
--metrics={"baseline":0,"xHeight":0,"capHeight":0,"pairs":{"Ta":[-4,1],"Tc":[-4,1],"Te":[-4,1],"To":[-4,1],"Tm":[-4,1],"Tn":[-4,1],"Tr":[-4,1],"Tu":[-4,1],"Tv":[-4,1],"Tw":[-4,1],"fB":[2,1],"fD":[2,1],"fE":[2,1],"fF":[2,1],"fH":[2,1],"fI":[2,1],"fK":[2,1],"fL":[2,1],"fM":[2,1],"fN":[2,1],"fP":[2,1],"fR":[2,1],"fW":[2,1],"fb":[2,1],"fh":[2,1],"fk":[2,1],"fC":[2,1],"fG":[2,1],"fO":[2,1],"fQ":[2,1],"fU":[2,1],"fl":[2,1],"lB":[1,1],"lD":[1,1],"lE":[1,1],"lF":[1,1],"lH":[1,1],"lI":[1,1],"lK":[1,1],"lL":[1,1],"lM":[1,1],"lN":[1,1],"lP":[1,1],"lR":[1,1],"lW":[1,1],"lb":[1,1],"lh":[1,1],"lk":[1,1],"lC":[1,1],"lG":[1,1],"lO":[1,1],"lQ":[1,1],"lU":[0,1,1,1],"ll":[0,1,1,1],"la":[0,1,1,1],"lc":[0,1,1,1],"le":[0,1,1,1],"lo":[0,1,1,1],"lm":[1,1],"ln":[1,1],"lr":[1,1],"lu":[0,1,1,1],"lv":[0,1,1,1],"lw":[0,1,1,1],"Fa":[-2,1],"Fc":[-2,1],"Fe":[-2,1],"Fo":[-2,1],"Fm":[-2,1],"Fn":[-2,1],"Fr":[-2,1],"Fu":[-2,1],"Fv":[-2,1],"Fw":[-2,1],"aT":[-4,2],"uT":[-4,2],"gT":[-4,2],"yT":[-4,2],"mT":[-4,2],"nT":[-4,2],"vT":[-4,2],"wT":[-4,2],"Td":[-4,0],"Tf":[-2,0],"Tg":[-4,0],"Tp":[-4,0],"Tq":[-4,0],"Ts":[-4,0],"Tt":[-2,0],"Tx":[-4,0],"Ty":[-4,0],"Tz":[-4,0],"TJ":[-4,0],"T<>":[-4,0],"bT":[-4,0],"cT":[-4,0],"eT":[-4,0],"fA":[1,0,2,0],"fT":[2,0],"fi":[2,0],"fj":[2,0],"fY":[2,0],"fJ":[-2,0],"fS":[2,0],"fV":[2,0],"fX":[2,0],"fZ":[2,0],"hT":[-4,0],"kT":[-4,0],"lA":[1,0],"lT":[-1,0],"ld":[0,0,1,0],"lf":[-1,0],"lg":[0,0,1,0],"li":[1,0],"lj":[1,0],"lp":[1,0],"lq":[0,0,1,0],"ls":[1,0],"lt":[-1,0],"lx":[1,0],"ly":[0,0,1,0],"lz":[1,0],"lY":[-1,0],"lJ":[1,0],"lS":[1,0],"lV":[-1,0],"lX":[1,0],"lZ":[1,0],"l<>":[-1,0],"oT":[-4,0],"pT":[-4,0],"qT":[-4,0],"rT":[-4,0],"rX":[-2,0],"rZ":[-2,0],"sT":[-4,0],"tT":[-2,0],"xT":[-4,0],"zT":[-4,0],"C<>":[-2,0],"Ef":[-2,0],"Et":[-2,0],"E<>":[-2,0],"Fd":[-2,0],"Ff":[-2,0],"Fg":[-2,0],"Fp":[-2,0],"Fq":[-2,0],"Fs":[-2,0],"Ft":[-2,0],"Fx":[-2,0],"Fy":[-2,0],"Fz":[-2,0],"FJ":[-2,0],"F<>":[-2,0],"YJ":[-2,0],"Kf":[-2,0],"Kt":[-2,0],"K<>":[-4,0],"LT":[-4,0],"Lf":[-2,0],"Lt":[-2,0],"LY":[-4,0],"LV":[-4,0],"L<>":[-4,0],"PJ":[-2,0],"X<>":[-2,0],"Z<>":[-2,0],"<22>T":[-4,0],"<22>X":[-2,0],"<22>Z":[-2,0]},"left":["BDEFHIKLMNPRWbhk","CGOQ","Ul","aceo","mnr","uvw"],"right":["AQ","DO","HIMNWd","JU","au","gy","mn","vw"]}
 | 
			
		||||
tracking=2
 | 
			
		||||
 | 
			
		||||
0	12
 | 
			
		||||
1	12
 | 
			
		||||
2	12
 | 
			
		||||
3	12
 | 
			
		||||
4	12
 | 
			
		||||
5	12
 | 
			
		||||
6	12
 | 
			
		||||
7	12
 | 
			
		||||
8	12
 | 
			
		||||
9	12
 | 
			
		||||
space	8
 | 
			
		||||
.	4
 | 
			
		||||
A	12
 | 
			
		||||
B	12
 | 
			
		||||
T	12
 | 
			
		||||
a	12
 | 
			
		||||
b	12
 | 
			
		||||
c	12
 | 
			
		||||
d	12
 | 
			
		||||
e	12
 | 
			
		||||
f	8
 | 
			
		||||
g	12
 | 
			
		||||
h	12
 | 
			
		||||
i	4
 | 
			
		||||
j	4
 | 
			
		||||
k	12
 | 
			
		||||
l	5
 | 
			
		||||
m	16
 | 
			
		||||
n	12
 | 
			
		||||
o	12
 | 
			
		||||
p	12
 | 
			
		||||
q	12
 | 
			
		||||
r	12
 | 
			
		||||
s	12
 | 
			
		||||
t	8
 | 
			
		||||
u	12
 | 
			
		||||
v	12
 | 
			
		||||
w	16
 | 
			
		||||
x	12
 | 
			
		||||
y	12
 | 
			
		||||
z	12
 | 
			
		||||
,	4
 | 
			
		||||
C	12
 | 
			
		||||
D	12
 | 
			
		||||
E	12
 | 
			
		||||
F	12
 | 
			
		||||
G	12
 | 
			
		||||
O	12
 | 
			
		||||
H	12
 | 
			
		||||
I	4
 | 
			
		||||
!	4
 | 
			
		||||
"	10
 | 
			
		||||
'	4
 | 
			
		||||
Y	12
 | 
			
		||||
{	8
 | 
			
		||||
|	4
 | 
			
		||||
}	8
 | 
			
		||||
J	12
 | 
			
		||||
K	14
 | 
			
		||||
L	12
 | 
			
		||||
M	14
 | 
			
		||||
N	14
 | 
			
		||||
P	12
 | 
			
		||||
Q	12
 | 
			
		||||
R	12
 | 
			
		||||
S	12
 | 
			
		||||
U	12
 | 
			
		||||
V	14
 | 
			
		||||
W	14
 | 
			
		||||
X	12
 | 
			
		||||
Z	12
 | 
			
		||||
/	12
 | 
			
		||||
\	12
 | 
			
		||||
[	6
 | 
			
		||||
]	6
 | 
			
		||||
:	4
 | 
			
		||||
;	4
 | 
			
		||||
^	12
 | 
			
		||||
_	10
 | 
			
		||||
`	8
 | 
			
		||||
~	16
 | 
			
		||||
¥	12
 | 
			
		||||
…	16
 | 
			
		||||
™	14
 | 
			
		||||
‼	10
 | 
			
		||||
©	18
 | 
			
		||||
®	18
 | 
			
		||||
<EFBFBD>	16
 | 
			
		||||
@	18
 | 
			
		||||
#	18
 | 
			
		||||
$	12
 | 
			
		||||
%	14
 | 
			
		||||
&	12
 | 
			
		||||
(	6
 | 
			
		||||
)	6
 | 
			
		||||
*	12
 | 
			
		||||
+	12
 | 
			
		||||
-	10
 | 
			
		||||
=	10
 | 
			
		||||
?	12
 | 
			
		||||
<	10
 | 
			
		||||
>	10
 | 
			
		||||
 | 
			
		||||
Ta	-4
 | 
			
		||||
Tc	-4
 | 
			
		||||
Te	-4
 | 
			
		||||
To	-4
 | 
			
		||||
Tm	-4
 | 
			
		||||
Tn	-4
 | 
			
		||||
Tr	-4
 | 
			
		||||
Tu	-4
 | 
			
		||||
Tv	-4
 | 
			
		||||
Tw	-4
 | 
			
		||||
fB	2
 | 
			
		||||
fD	2
 | 
			
		||||
fE	2
 | 
			
		||||
fF	2
 | 
			
		||||
fH	2
 | 
			
		||||
fI	2
 | 
			
		||||
fK	2
 | 
			
		||||
fL	2
 | 
			
		||||
fM	2
 | 
			
		||||
fN	2
 | 
			
		||||
fP	2
 | 
			
		||||
fR	2
 | 
			
		||||
fW	2
 | 
			
		||||
fb	2
 | 
			
		||||
fh	2
 | 
			
		||||
fk	2
 | 
			
		||||
fC	2
 | 
			
		||||
fG	2
 | 
			
		||||
fO	2
 | 
			
		||||
fQ	2
 | 
			
		||||
fU	2
 | 
			
		||||
fl	2
 | 
			
		||||
lB	1
 | 
			
		||||
lD	1
 | 
			
		||||
lE	1
 | 
			
		||||
lF	1
 | 
			
		||||
lH	1
 | 
			
		||||
lI	1
 | 
			
		||||
lK	1
 | 
			
		||||
lL	1
 | 
			
		||||
lM	1
 | 
			
		||||
lN	1
 | 
			
		||||
lP	1
 | 
			
		||||
lR	1
 | 
			
		||||
lW	1
 | 
			
		||||
lb	1
 | 
			
		||||
lh	1
 | 
			
		||||
lk	1
 | 
			
		||||
lC	1
 | 
			
		||||
lG	1
 | 
			
		||||
lO	1
 | 
			
		||||
lQ	1
 | 
			
		||||
lm	1
 | 
			
		||||
ln	1
 | 
			
		||||
lr	1
 | 
			
		||||
Fa	-2
 | 
			
		||||
Fc	-2
 | 
			
		||||
Fe	-2
 | 
			
		||||
Fo	-2
 | 
			
		||||
Fm	-2
 | 
			
		||||
Fn	-2
 | 
			
		||||
Fr	-2
 | 
			
		||||
Fu	-2
 | 
			
		||||
Fv	-2
 | 
			
		||||
Fw	-2
 | 
			
		||||
aT	-4
 | 
			
		||||
uT	-4
 | 
			
		||||
gT	-4
 | 
			
		||||
yT	-4
 | 
			
		||||
mT	-4
 | 
			
		||||
nT	-4
 | 
			
		||||
vT	-4
 | 
			
		||||
wT	-4
 | 
			
		||||
Td	-4
 | 
			
		||||
Tf	-2
 | 
			
		||||
Tg	-4
 | 
			
		||||
Tp	-4
 | 
			
		||||
Tq	-4
 | 
			
		||||
Ts	-4
 | 
			
		||||
Tt	-2
 | 
			
		||||
Tx	-4
 | 
			
		||||
Ty	-4
 | 
			
		||||
Tz	-4
 | 
			
		||||
TJ	-4
 | 
			
		||||
T<EFBFBD>	-4
 | 
			
		||||
bT	-4
 | 
			
		||||
cT	-4
 | 
			
		||||
eT	-4
 | 
			
		||||
fA	1
 | 
			
		||||
fT	2
 | 
			
		||||
fi	2
 | 
			
		||||
fj	2
 | 
			
		||||
fY	2
 | 
			
		||||
fJ	-2
 | 
			
		||||
fS	2
 | 
			
		||||
fV	2
 | 
			
		||||
fX	2
 | 
			
		||||
fZ	2
 | 
			
		||||
hT	-4
 | 
			
		||||
kT	-4
 | 
			
		||||
lA	1
 | 
			
		||||
lT	-1
 | 
			
		||||
lf	-1
 | 
			
		||||
li	1
 | 
			
		||||
lj	1
 | 
			
		||||
lp	1
 | 
			
		||||
ls	1
 | 
			
		||||
lt	-1
 | 
			
		||||
lx	1
 | 
			
		||||
lz	1
 | 
			
		||||
lY	-1
 | 
			
		||||
lJ	1
 | 
			
		||||
lS	1
 | 
			
		||||
lV	-1
 | 
			
		||||
lX	1
 | 
			
		||||
lZ	1
 | 
			
		||||
l<EFBFBD>	-1
 | 
			
		||||
oT	-4
 | 
			
		||||
pT	-4
 | 
			
		||||
qT	-4
 | 
			
		||||
rT	-4
 | 
			
		||||
rX	-2
 | 
			
		||||
rZ	-2
 | 
			
		||||
sT	-4
 | 
			
		||||
tT	-2
 | 
			
		||||
xT	-4
 | 
			
		||||
zT	-4
 | 
			
		||||
C<EFBFBD>	-2
 | 
			
		||||
Ef	-2
 | 
			
		||||
Et	-2
 | 
			
		||||
E<EFBFBD>	-2
 | 
			
		||||
Fd	-2
 | 
			
		||||
Ff	-2
 | 
			
		||||
Fg	-2
 | 
			
		||||
Fp	-2
 | 
			
		||||
Fq	-2
 | 
			
		||||
Fs	-2
 | 
			
		||||
Ft	-2
 | 
			
		||||
Fx	-2
 | 
			
		||||
Fy	-2
 | 
			
		||||
Fz	-2
 | 
			
		||||
FJ	-2
 | 
			
		||||
F<EFBFBD>	-2
 | 
			
		||||
YJ	-2
 | 
			
		||||
Kf	-2
 | 
			
		||||
Kt	-2
 | 
			
		||||
K<EFBFBD>	-4
 | 
			
		||||
LT	-4
 | 
			
		||||
Lf	-2
 | 
			
		||||
Lt	-2
 | 
			
		||||
LY	-4
 | 
			
		||||
LV	-4
 | 
			
		||||
L<EFBFBD>	-4
 | 
			
		||||
PJ	-2
 | 
			
		||||
X<EFBFBD>	-2
 | 
			
		||||
Z<EFBFBD>	-2
 | 
			
		||||
<EFBFBD>T	-4
 | 
			
		||||
<EFBFBD>X	-2
 | 
			
		||||
<EFBFBD>Z	-2
 | 
			
		||||
							
								
								
									
										31
									
								
								source/ground.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								source/ground.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
class("Ground").extends(playdate.graphics.sprite)
 | 
			
		||||
 | 
			
		||||
function Ground:init(x, y, player)
 | 
			
		||||
    local groundImage = playdate.graphics.image.new("sprites/groundFin")
 | 
			
		||||
    Ground.super.init(self, groundImage)
 | 
			
		||||
    self:moveTo(x, y)
 | 
			
		||||
    self:setZIndex(100)
 | 
			
		||||
    self:setTag(3)
 | 
			
		||||
    self:setCollideRect(0, 28, 800, 10)
 | 
			
		||||
 | 
			
		||||
    Ground.moveSpeed = 2
 | 
			
		||||
    Ground.player = player
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Ground:setMoveSpeed(speed)
 | 
			
		||||
    Ground.moveSpeed = speed
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Ground:update()
 | 
			
		||||
    if Ground.player.isMovingRight() == false then
 | 
			
		||||
        Ground.moveSpeed = 0.2
 | 
			
		||||
    else
 | 
			
		||||
        Ground.moveSpeed = 1
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if self.x <= 0 then
 | 
			
		||||
        self:moveWithCollisions(400, self.y)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    self:moveWithCollisions(self.x-Ground.moveSpeed, self.y)
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										68
									
								
								source/level.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								source/level.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
local pd <const> = playdate
 | 
			
		||||
local gfx <const> = playdate.graphics
 | 
			
		||||
 | 
			
		||||
import "player"
 | 
			
		||||
import "ground"
 | 
			
		||||
import "backgroundSprite"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class("Level").extends()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
-- This function relies on the use of timers, so the timer core library
 | 
			
		||||
-- must be imported, and updateTimers() must be called in the update loop
 | 
			
		||||
local function screenShake(shakeTime, shakeMagnitude)
 | 
			
		||||
    -- Creating a value timer that goes from shakeMagnitude to 0, over
 | 
			
		||||
    -- the course of 'shakeTime' milliseconds
 | 
			
		||||
    local shakeTimer = playdate.timer.new(shakeTime, shakeMagnitude, 0)
 | 
			
		||||
    -- Every frame when the timer is active, we shake the screen
 | 
			
		||||
    shakeTimer.updateCallback = function(timer)
 | 
			
		||||
        -- Using the timer value, so the shaking magnitude
 | 
			
		||||
        -- gradually decreases over time
 | 
			
		||||
        local magnitude = math.floor(timer.value)
 | 
			
		||||
        local shakeX = math.random(-magnitude, magnitude)
 | 
			
		||||
        local shakeY = math.random(-magnitude, magnitude)
 | 
			
		||||
        playdate.display.setOffset(shakeX, shakeY)
 | 
			
		||||
    end
 | 
			
		||||
    -- Resetting the display offset at the end of the screen shake
 | 
			
		||||
    shakeTimer.timerEndedCallback = function()
 | 
			
		||||
        playdate.display.setOffset(0, 0)
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function Level:init()
 | 
			
		||||
    player = Player(30, 30)
 | 
			
		||||
    player:add()
 | 
			
		||||
    
 | 
			
		||||
    ground = Ground(400, 225, player)
 | 
			
		||||
    ground:add()
 | 
			
		||||
    
 | 
			
		||||
    BackGround()
 | 
			
		||||
 | 
			
		||||
    local fp = playdate.sound.fileplayer.new( "audio/war" )
 | 
			
		||||
    local hello = playdate.sound.fileplayer.new( "audio/hello" )
 | 
			
		||||
    
 | 
			
		||||
    hello:play(1)
 | 
			
		||||
    fp:setVolume(0.7)
 | 
			
		||||
    fp:play(0)
 | 
			
		||||
 | 
			
		||||
    Level.telemLostSound = playdate.sound.fileplayer.new( "audio/telemko" )
 | 
			
		||||
    Level.telemLostSoundPlayed = false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Level:update()
 | 
			
		||||
    if player.isDead() then
 | 
			
		||||
        if not Level.telemLostSoundPlayed then
 | 
			
		||||
            Level.telemLostSound:play(1)
 | 
			
		||||
            Level.telemLostSoundPlayed = true
 | 
			
		||||
            screenShake(500, 5)
 | 
			
		||||
        end
 | 
			
		||||
		gfx.drawText("Telemetry Lost", 100, 110)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
    local bat = player.getBat()
 | 
			
		||||
    bat = math.floor(bat/100)
 | 
			
		||||
    gfx.drawText("Bat: " .. bat, 10, 215)
 | 
			
		||||
    -- gfx.drawText("Dis: " .. player.dischargeRate, 100, 215)
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										512
									
								
								source/lib/AnimatedSprite.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										512
									
								
								source/lib/AnimatedSprite.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,512 @@
 | 
			
		||||
-----------------------------------------------
 | 
			
		||||
--- Sprite class extension with support of  ---
 | 
			
		||||
--- imagetables and finite state machine,   ---
 | 
			
		||||
--- with json configuration and autoplay.   ---
 | 
			
		||||
---            By @Whitebrim   git.brim.ml  ---
 | 
			
		||||
-----------------------------------------------
 | 
			
		||||
 | 
			
		||||
-- You can find examples and docs at https://github.com/Whitebrim/AnimatedSprite/wiki
 | 
			
		||||
-- Comments use EmmyLua style
 | 
			
		||||
 | 
			
		||||
import 'CoreLibs/object'
 | 
			
		||||
import 'CoreLibs/sprites'
 | 
			
		||||
local gfx <const> = playdate.graphics
 | 
			
		||||
local function emptyFunc()end
 | 
			
		||||
 | 
			
		||||
class("AnimatedSprite").extends(gfx.sprite)
 | 
			
		||||
 | 
			
		||||
---@param imagetable table|string actual imagetable or path
 | 
			
		||||
---@param states? table If provided, calls `setStates(states)` after initialisation
 | 
			
		||||
---@param animate? boolean If `True`, then the animation of default state will start after initialisation. Default: `False`
 | 
			
		||||
function AnimatedSprite.new(imagetable, states, animate)
 | 
			
		||||
	return AnimatedSprite(imagetable, states, animate)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function AnimatedSprite:init(imagetable, states, animate)
 | 
			
		||||
	AnimatedSprite.super.init(self)
 | 
			
		||||
 | 
			
		||||
	---@type table
 | 
			
		||||
	if (type(imagetable) == "string") then
 | 
			
		||||
		imagetable = gfx.imagetable.new(imagetable)
 | 
			
		||||
	end
 | 
			
		||||
	self.imagetable = imagetable
 | 
			
		||||
	assert(self.imagetable, "Imagetable is nil. Check if it was loaded correctly.")
 | 
			
		||||
 | 
			
		||||
	self:add()
 | 
			
		||||
 | 
			
		||||
	self.globalFlip = gfx.kImageUnflipped
 | 
			
		||||
	self.defaultState = "default"
 | 
			
		||||
	self.states = {
 | 
			
		||||
		default = {
 | 
			
		||||
			name = "default",
 | 
			
		||||
			---@type integer|string
 | 
			
		||||
			firstFrameIndex = 1,
 | 
			
		||||
			framesCount = #self.imagetable,
 | 
			
		||||
			animationStartingFrame = 1,
 | 
			
		||||
			tickStep = 1,
 | 
			
		||||
			frameStep = 1,
 | 
			
		||||
			reverse = false,
 | 
			
		||||
			---@type boolean|integer
 | 
			
		||||
			loop = true,
 | 
			
		||||
			yoyo = false,
 | 
			
		||||
			flip = gfx.kImageUnflipped,
 | 
			
		||||
			xScale = 1,
 | 
			
		||||
			yScale = 1,
 | 
			
		||||
			nextAnimation = nil,
 | 
			
		||||
 | 
			
		||||
			onFrameChangedEvent = emptyFunc,
 | 
			
		||||
			onStateChangedEvent = emptyFunc,
 | 
			
		||||
			onLoopFinishedEvent = emptyFunc,
 | 
			
		||||
			onAnimationEndEvent = emptyFunc
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	self._enabled = false
 | 
			
		||||
	self._currentFrame = 0 -- purposely
 | 
			
		||||
	self._ticks = 1
 | 
			
		||||
	self._previousTicks = 1
 | 
			
		||||
	self._loopsFinished = 0
 | 
			
		||||
	self._currentYoyoDirection = true
 | 
			
		||||
 | 
			
		||||
	if (states) then
 | 
			
		||||
		self:setStates(states)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	if (animate) then
 | 
			
		||||
		self:playAnimation()
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function drawFrame(self)
 | 
			
		||||
	local state = self.states[self.currentState]
 | 
			
		||||
	self:setImage(self._image, state.flip ~ self.globalFlip, state.xScale, state.yScale)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function setImage(self)
 | 
			
		||||
	local frames = self.states[self.currentState].frames
 | 
			
		||||
	if (frames) then
 | 
			
		||||
		self._image = self.imagetable[frames[self._currentFrame]]
 | 
			
		||||
	else
 | 
			
		||||
		self._image = self.imagetable[self._currentFrame]
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Start/resume the animation  
 | 
			
		||||
---If `currentState` is nil then `defaultState` will be choosen as current
 | 
			
		||||
function AnimatedSprite:playAnimation()
 | 
			
		||||
 | 
			
		||||
	local state = self.states[self.currentState]
 | 
			
		||||
 | 
			
		||||
	if (type(self.currentState) == 'nil') then
 | 
			
		||||
		self.currentState = self.defaultState
 | 
			
		||||
		state = self.states[self.currentState]
 | 
			
		||||
		self._currentFrame = state.animationStartingFrame + state.firstFrameIndex - 1
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	if (self._currentFrame == 0) then
 | 
			
		||||
		self._currentFrame = state.animationStartingFrame + state.firstFrameIndex - 1
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	self._enabled = true
 | 
			
		||||
	self._previousTicks = self._ticks
 | 
			
		||||
	setImage(self)
 | 
			
		||||
	drawFrame(self)
 | 
			
		||||
	if (state.framesCount == 1) then
 | 
			
		||||
		self._loopsFinished += 1
 | 
			
		||||
		state.onFrameChangedEvent(self)
 | 
			
		||||
		state.onLoopFinishedEvent(self)
 | 
			
		||||
	else
 | 
			
		||||
		state.onFrameChangedEvent(self)
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Stop the animation without resetting
 | 
			
		||||
function AnimatedSprite:pauseAnimation()
 | 
			
		||||
	self._enabled = false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Play the animation without resetting
 | 
			
		||||
function AnimatedSprite:resumeAnimation()
 | 
			
		||||
	self._enabled = true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Play/Pause animation based on current state
 | 
			
		||||
function AnimatedSprite:toggleAnimation()
 | 
			
		||||
	if (self._enabled) then
 | 
			
		||||
		self:pauseAnimation()
 | 
			
		||||
	else
 | 
			
		||||
		self:resumeAnimation()
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Stop and reset the animation  
 | 
			
		||||
---After calling `playAnimation` the animation will start from `defaultState` 
 | 
			
		||||
function AnimatedSprite:stopAnimation()
 | 
			
		||||
	self:pauseAnimation()
 | 
			
		||||
	self.currentState = nil
 | 
			
		||||
	self._currentFrame = 0 -- purposely
 | 
			
		||||
	self._ticks = 1
 | 
			
		||||
	self._previousTicks = self._ticks
 | 
			
		||||
	self._loopsFinished = 0
 | 
			
		||||
	self._currentYoyoDirection = true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function addState(self, params)
 | 
			
		||||
	assert(params.name, "The animation state is unnamed!")
 | 
			
		||||
	if (self.defaultState == "default") then
 | 
			
		||||
		self.defaultState = params.name -- Init first added state as default
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	self.states[params.name] = {}
 | 
			
		||||
	local state = self.states[params.name]
 | 
			
		||||
	setmetatable(state, {__index = self.states.default})
 | 
			
		||||
 | 
			
		||||
	params = params or {}
 | 
			
		||||
 | 
			
		||||
	state.name = params.name
 | 
			
		||||
	if (params.frames ~= nil) then
 | 
			
		||||
		state["frames"] = params.frames -- Custom animation for non-sequential frames from the imagetable
 | 
			
		||||
		params.firstFrameIndex = 1
 | 
			
		||||
		params.framesCount = #params.frames
 | 
			
		||||
	end
 | 
			
		||||
	if (type(params.firstFrameIndex) == "string") then
 | 
			
		||||
		local thatState = self.states[params.firstFrameIndex]
 | 
			
		||||
		state["firstFrameIndex"] = thatState.firstFrameIndex + thatState.framesCount
 | 
			
		||||
	else
 | 
			
		||||
		state["firstFrameIndex"] = params.firstFrameIndex -- index in the imagetable for the firstFrame
 | 
			
		||||
	end
 | 
			
		||||
	state["framesCount"] = params.framesCount and params.framesCount or (self.states.default.framesCount - state.firstFrameIndex + 1) -- This state frames count
 | 
			
		||||
	state["nextAnimation"] = params.nextAnimation -- Animation to switch to after this finishes
 | 
			
		||||
	if (params.nextAnimation == nil) then
 | 
			
		||||
		state["loop"] = params.loop -- You can put in number of loops or true for endless loop
 | 
			
		||||
	else
 | 
			
		||||
		state["loop"] = params.loop or false
 | 
			
		||||
	end
 | 
			
		||||
	state["reverse"] = params.reverse -- You can reverse animation sequence
 | 
			
		||||
	state["animationStartingFrame"] = params.animationStartingFrame or (state.reverse and state.framesCount or 1) -- Frame to start the animation from
 | 
			
		||||
	state["tickStep"] = params.tickStep -- Speed of animation (2 = every second frame)
 | 
			
		||||
	state["frameStep"] = params.frameStep -- Number of images to skip on next frame
 | 
			
		||||
	state["yoyo"] = params.yoyo -- Ping-pong animation (from 1 to n to 1 to n)
 | 
			
		||||
	state["flip"] = params.flip -- You can set up flip mode, read Playdate SDK Docs for more info
 | 
			
		||||
	state["xScale"] = params.xScale -- Optional scale for horizontal axis
 | 
			
		||||
	state["yScale"] = params.yScale -- Optional scale for vertical axis
 | 
			
		||||
 | 
			
		||||
	state["onFrameChangedEvent"] = params.onFrameChangedEvent -- Event that will be raised when animation moves to the next frame
 | 
			
		||||
	state["onStateChangedEvent"] = params.onStateChangedEvent -- Event that will be raised when animation state changes
 | 
			
		||||
	state["onLoopFinishedEvent"] = params.onLoopFinishedEvent -- Event that will be raised when animation changes to the final frame
 | 
			
		||||
	state["onAnimationEndEvent"] = params.onAnimationEndEvent -- Event that will be raised after animation in this state ends
 | 
			
		||||
 | 
			
		||||
	return state
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Parse `json` file with animation configuration
 | 
			
		||||
---@param path string Path to the file
 | 
			
		||||
---@return table config You can use it in `setStates(states)`
 | 
			
		||||
function AnimatedSprite.loadStates(path)
 | 
			
		||||
	return assert(json.decodeFile(path), "Requested JSON parse failed. Path: " .. path)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Get imagetable's frame index that is currently displayed
 | 
			
		||||
---@return integer index Current frame index
 | 
			
		||||
function AnimatedSprite:getCurrentFrameIndex()
 | 
			
		||||
	if (self.currentState and self.states[self.currentState].frames) then
 | 
			
		||||
		return self.states[self.currentState].frames[self._currentFrame]
 | 
			
		||||
	else
 | 
			
		||||
		return self._currentFrame
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Get the current frame's local index in the state  
 | 
			
		||||
---I.e. 1, 2, 3, N, where N = number of frames in this state  
 | 
			
		||||
---Also works if `frames` property was provided
 | 
			
		||||
---@return integer index Current frame local index
 | 
			
		||||
function AnimatedSprite:getCurrentFrameLocalIndex()
 | 
			
		||||
	return self.currentFrame - self.states[self.currentState].firstFrameIndex + 1
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Get reference to the current state
 | 
			
		||||
---@return table state Reference to the current state
 | 
			
		||||
function AnimatedSprite:getCurrentState()
 | 
			
		||||
	return self.states[self.currentState]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Get reference to the current states
 | 
			
		||||
---@return table states Reference to the current states
 | 
			
		||||
function AnimatedSprite:getLocalStates()
 | 
			
		||||
	return self.states
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Get copy of the states
 | 
			
		||||
---@return table states Deepcopy of the current states
 | 
			
		||||
function AnimatedSprite:copyLocalStates()
 | 
			
		||||
	return table.deepcopy(self.states)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Add all states from the `states` to the current state machine (overwrites values in case of conflicts)
 | 
			
		||||
---@param states table State machine state list, you can get one by calling `loadStates`
 | 
			
		||||
---@param animate? boolean If `True`, then the animation of default/current state will start immediately after. Default: `False`
 | 
			
		||||
---@param defaultState? string If provided, changes default state
 | 
			
		||||
function AnimatedSprite:setStates(states, animate, defaultState)
 | 
			
		||||
	local statesCount = #states
 | 
			
		||||
 | 
			
		||||
	local function proceedState(state)
 | 
			
		||||
		if (state.name ~= "default") then
 | 
			
		||||
			addState(self, state)
 | 
			
		||||
		else
 | 
			
		||||
			local default = self.states.default
 | 
			
		||||
			for key, value in pairs(state) do
 | 
			
		||||
				default[key] = value
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	if (statesCount == 0) then
 | 
			
		||||
		proceedState(states)
 | 
			
		||||
		if (defaultState) then
 | 
			
		||||
			self.defaultState = defaultState
 | 
			
		||||
		end
 | 
			
		||||
		if (animate) then
 | 
			
		||||
			self:playAnimation()
 | 
			
		||||
		end
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	for i = 1, statesCount do
 | 
			
		||||
		proceedState(states[i])
 | 
			
		||||
	end
 | 
			
		||||
	if (defaultState) then
 | 
			
		||||
		self.defaultState = defaultState
 | 
			
		||||
	end
 | 
			
		||||
	if (animate) then
 | 
			
		||||
		self:playAnimation()
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Add new state to the state machine
 | 
			
		||||
---@param name string Name of the state, should be unique, used as id
 | 
			
		||||
---@param startFrame? integer Index of the first frame in the imagetable (starts from 1). Default: `1` (from states.default)
 | 
			
		||||
---@param endFrame? integer Index of the last frame in the imagetable. Default: last frame (from states.default)
 | 
			
		||||
---@param params? table See examples
 | 
			
		||||
---@param animate? boolean If `True`, then the animation of this state will start immediately after. Default: `False`
 | 
			
		||||
function AnimatedSprite:addState(name, startFrame, endFrame, params, animate)
 | 
			
		||||
	params = params or {}
 | 
			
		||||
	params.firstFrameIndex = startFrame or 1
 | 
			
		||||
	params.framesCount = endFrame and (endFrame - params.firstFrameIndex + 1) or nil
 | 
			
		||||
	params.name = name
 | 
			
		||||
 | 
			
		||||
	addState(self, params)
 | 
			
		||||
 | 
			
		||||
	if (animate) then
 | 
			
		||||
		self.currentState = name
 | 
			
		||||
		self:playAnimation()
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	return {
 | 
			
		||||
		asDefault = function ()
 | 
			
		||||
			self.defaultState = name
 | 
			
		||||
		end
 | 
			
		||||
	}
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Change current state to an existing state
 | 
			
		||||
---@param name string New state name
 | 
			
		||||
---@param play? boolean If new animation should be played right away. Default: `True`
 | 
			
		||||
function AnimatedSprite:changeState(name, play)
 | 
			
		||||
	if (name == self.currentState) then
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
	play = type(play) == "nil" and true or play
 | 
			
		||||
	local state = self.states[name]
 | 
			
		||||
	assert (state, "There's no state named \""..name.."\".")
 | 
			
		||||
	self.currentState = name
 | 
			
		||||
	self._currentFrame = 0 -- purposely
 | 
			
		||||
	self._loopsFinished = 0
 | 
			
		||||
	self._currentYoyoDirection = true
 | 
			
		||||
	state.onStateChangedEvent(self)
 | 
			
		||||
	if (play) then
 | 
			
		||||
		self:playAnimation()
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Change current state to an existing state and start from selected frame  
 | 
			
		||||
---If new state is the same as current state, nothing will change
 | 
			
		||||
---@param name string New state name
 | 
			
		||||
---@param frameIndex integer Local frame index of this state. Indexing starts from 1. Default: `1`
 | 
			
		||||
---@param play? boolean If new animation should be played right away. Default: `True`
 | 
			
		||||
function AnimatedSprite:changeStateAndSelectFrame(name, frameIndex, play)
 | 
			
		||||
	if (name == self.currentState) then
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
	play = type(play) == "nil" and true or play
 | 
			
		||||
	frameIndex = frameIndex or 1
 | 
			
		||||
	local state = self.states[name]
 | 
			
		||||
	assert (state, "There's no state named \""..name.."\".")
 | 
			
		||||
	self.currentState = name
 | 
			
		||||
	self._currentFrame = state.firstFrameIndex + frameIndex - 1
 | 
			
		||||
	self._loopsFinished = 0
 | 
			
		||||
	self._currentYoyoDirection = true
 | 
			
		||||
	state.onStateChangedEvent(self)
 | 
			
		||||
	if (play) then
 | 
			
		||||
		self:playAnimation()
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Force animation state machine to switch to the next state
 | 
			
		||||
---@param instant? boolean If `False` change will be performed after the final frame of this loop iteration. Default: `True`
 | 
			
		||||
---@param state? string Name of the state to change to. If not provided, animator will try to change to the next animation, else stop the animation
 | 
			
		||||
function AnimatedSprite:forceNextAnimation(instant, state)
 | 
			
		||||
	instant = type(instant) == "nil" and true or instant
 | 
			
		||||
	local currentState = self.states[self.currentState]
 | 
			
		||||
	self.forcedState = state
 | 
			
		||||
 | 
			
		||||
	if (instant) then
 | 
			
		||||
		self.forcedSwitchOnLoop = nil
 | 
			
		||||
		currentState.onAnimationEndEvent(self)
 | 
			
		||||
		if (currentState.name == self.currentState) then -- If state was not changed during the event then proceed
 | 
			
		||||
			if (type(self.forcedState) == "string") then
 | 
			
		||||
				self:changeState(self.forcedState)
 | 
			
		||||
				self.forcedState = nil
 | 
			
		||||
			elseif (currentState.nextAnimation) then
 | 
			
		||||
				self:changeState(currentState.nextAnimation)
 | 
			
		||||
			else
 | 
			
		||||
				self:stopAnimation()
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	else
 | 
			
		||||
		self.forcedSwitchOnLoop = self._loopsFinished + 1
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Set default state
 | 
			
		||||
---@param name string Name of an existing state
 | 
			
		||||
function AnimatedSprite:setDefaultState(name)
 | 
			
		||||
	assert (self.states[name], "State name is nil.")
 | 
			
		||||
	self.defaultState = name
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Print all states from this state machine to the console for debug purposes
 | 
			
		||||
function AnimatedSprite:printAllStates()
 | 
			
		||||
	printTable(self.states)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Procees the animation to the next step without redrawing the sprite
 | 
			
		||||
local function processAnimation(self)
 | 
			
		||||
	local state = self.states[self.currentState]
 | 
			
		||||
 | 
			
		||||
	local function changeFrame(value)
 | 
			
		||||
		value += state.firstFrameIndex
 | 
			
		||||
		self._currentFrame = value
 | 
			
		||||
		state.onFrameChangedEvent(self)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local reverse = state.reverse
 | 
			
		||||
	local frame = self._currentFrame - state.firstFrameIndex
 | 
			
		||||
	local framesCount = state.framesCount
 | 
			
		||||
	local frameStep = state.frameStep
 | 
			
		||||
 | 
			
		||||
	if (self._currentFrame == 0) then -- true only after changing state
 | 
			
		||||
		self._currentFrame = state.animationStartingFrame + state.firstFrameIndex - 1
 | 
			
		||||
		if (framesCount == 1) then
 | 
			
		||||
			self._loopsFinished += 1
 | 
			
		||||
			state.onFrameChangedEvent(self)
 | 
			
		||||
			state.onLoopFinishedEvent(self)
 | 
			
		||||
			return
 | 
			
		||||
		else
 | 
			
		||||
			state.onFrameChangedEvent(self)
 | 
			
		||||
		end
 | 
			
		||||
		setImage(self)
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	if (framesCount == 1) then -- if this state is only 1 frame long
 | 
			
		||||
		self._loopsFinished += 1
 | 
			
		||||
		state.onFrameChangedEvent(self)
 | 
			
		||||
		state.onLoopFinishedEvent(self)
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	if (state.yoyo) then
 | 
			
		||||
		if (reverse ~= self._currentYoyoDirection) then
 | 
			
		||||
			if (frame + frameStep + 1 < framesCount) then
 | 
			
		||||
				changeFrame(frame + frameStep)
 | 
			
		||||
			else
 | 
			
		||||
				if (frame ~= framesCount - 1) then
 | 
			
		||||
					self._loopsFinished += 1
 | 
			
		||||
					changeFrame(2 * framesCount - frame - frameStep - 2)
 | 
			
		||||
					state.onLoopFinishedEvent(self)
 | 
			
		||||
				else
 | 
			
		||||
					changeFrame(2 * framesCount - frame - frameStep - 2)
 | 
			
		||||
				end
 | 
			
		||||
				self._currentYoyoDirection = not self._currentYoyoDirection
 | 
			
		||||
			end
 | 
			
		||||
		else
 | 
			
		||||
			if (frame - frameStep > 0) then
 | 
			
		||||
				changeFrame(frame - frameStep)
 | 
			
		||||
			else
 | 
			
		||||
				if (frame ~= 0) then
 | 
			
		||||
					self._loopsFinished += 1
 | 
			
		||||
					changeFrame(frameStep - frame)
 | 
			
		||||
					state.onLoopFinishedEvent(self)
 | 
			
		||||
				else
 | 
			
		||||
					changeFrame(frameStep - frame)
 | 
			
		||||
				end
 | 
			
		||||
				self._currentYoyoDirection = not self._currentYoyoDirection
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	else
 | 
			
		||||
		if (reverse) then
 | 
			
		||||
			if (frame - frameStep > 0) then
 | 
			
		||||
				changeFrame(frame - frameStep)
 | 
			
		||||
			else
 | 
			
		||||
				if (frame ~= 0) then
 | 
			
		||||
					self._loopsFinished += 1
 | 
			
		||||
					changeFrame((frame - frameStep) % framesCount)
 | 
			
		||||
					state.onLoopFinishedEvent(self)
 | 
			
		||||
				else
 | 
			
		||||
					changeFrame((frame - frameStep) % framesCount)
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		else
 | 
			
		||||
			if (frame + frameStep + 1 < framesCount) then
 | 
			
		||||
				changeFrame(frame + frameStep)
 | 
			
		||||
			else
 | 
			
		||||
				if (frame ~= framesCount - 1) then
 | 
			
		||||
					self._loopsFinished += 1
 | 
			
		||||
					changeFrame((frame + frameStep) % framesCount)
 | 
			
		||||
					state.onLoopFinishedEvent(self)
 | 
			
		||||
				else
 | 
			
		||||
					changeFrame((frame + frameStep) % framesCount)
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	setImage(self)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Called by default in the `:update()` function.  
 | 
			
		||||
---Must be called once per frame if you overwrite `:update()`.  
 | 
			
		||||
---Invoke manually to move the animation to the next frame.
 | 
			
		||||
function AnimatedSprite:updateAnimation()
 | 
			
		||||
	if (self._enabled) then
 | 
			
		||||
		self._ticks += 1
 | 
			
		||||
		if ((self._ticks - self._previousTicks) >= self.states[self.currentState].tickStep) then
 | 
			
		||||
			local state = self.states[self.currentState]
 | 
			
		||||
			local loop = state.loop
 | 
			
		||||
			local loopsFinished = self._loopsFinished
 | 
			
		||||
			if (type(loop) == "number" and loop <= loopsFinished or
 | 
			
		||||
				type(loop) == "boolean" and not loop and loopsFinished >= 1 or
 | 
			
		||||
				self.forcedSwitchOnLoop == loopsFinished) then
 | 
			
		||||
				self:forceNextAnimation(true)
 | 
			
		||||
				return
 | 
			
		||||
			end
 | 
			
		||||
			processAnimation(self)
 | 
			
		||||
			drawFrame(self)
 | 
			
		||||
			self._previousTicks += state.tickStep
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function AnimatedSprite:update()
 | 
			
		||||
	self:updateAnimation()
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										55
									
								
								source/main.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								source/main.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
-- CoreLibs
 | 
			
		||||
import "CoreLibs/object"
 | 
			
		||||
import "CoreLibs/graphics"
 | 
			
		||||
import "CoreLibs/sprites"
 | 
			
		||||
import "CoreLibs/timer"
 | 
			
		||||
import "CoreLibs/crank"
 | 
			
		||||
 | 
			
		||||
local pd <const> = playdate
 | 
			
		||||
local gfx <const> = pd.graphics
 | 
			
		||||
 | 
			
		||||
TAGS = {
 | 
			
		||||
    Pickup = 1,
 | 
			
		||||
    Player = 2,
 | 
			
		||||
    Hazard = 3
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Z_INDEXES = {
 | 
			
		||||
    Ground = 100,
 | 
			
		||||
    Pickup = 50,
 | 
			
		||||
    Player = 20
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
local font = gfx.font.new('font/Mini Sans 2X')
 | 
			
		||||
 | 
			
		||||
gfx.setFont(font)
 | 
			
		||||
 | 
			
		||||
-- Libraries
 | 
			
		||||
import "lib/AnimatedSprite"
 | 
			
		||||
playdate.display.setRefreshRate(50)
 | 
			
		||||
 | 
			
		||||
-- Game
 | 
			
		||||
import "level"
 | 
			
		||||
 | 
			
		||||
level = nil
 | 
			
		||||
 | 
			
		||||
local function initialize()
 | 
			
		||||
    -- Make it different, every time!
 | 
			
		||||
    math.randomseed(playdate.getSecondsSinceEpoch())
 | 
			
		||||
 | 
			
		||||
    -- Init all the things!
 | 
			
		||||
    level = Level()
 | 
			
		||||
    playdate.resetElapsedTime()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
initialize()
 | 
			
		||||
 | 
			
		||||
function pd.update()
 | 
			
		||||
	gfx.sprite.update()
 | 
			
		||||
	pd.timer.updateTimers()
 | 
			
		||||
	pd.drawFPS(10,0)
 | 
			
		||||
 | 
			
		||||
    if level then
 | 
			
		||||
        level.update()
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										0
									
								
								source/menu.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								source/menu.lua
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										6
									
								
								source/pdxinfo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								source/pdxinfo
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
name=FPVRun
 | 
			
		||||
author=ut3usw
 | 
			
		||||
description=My first game
 | 
			
		||||
bundleID=com.ut3usw.fpv
 | 
			
		||||
version=0.0.1
 | 
			
		||||
buildNumber=1
 | 
			
		||||
							
								
								
									
										189
									
								
								source/player.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										189
									
								
								source/player.lua
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,189 @@
 | 
			
		||||
local pd <const> = playdate
 | 
			
		||||
local gfx <const> = playdate.graphics
 | 
			
		||||
 | 
			
		||||
class('Player').extends(AnimatedSprite)
 | 
			
		||||
 | 
			
		||||
function Player:init(x, y, gameManager)
 | 
			
		||||
    self.gameManager = gameManager
 | 
			
		||||
 | 
			
		||||
    local playerImageTable = gfx.imagetable.new("sprites/player-table-48-48")
 | 
			
		||||
    Player.super.init(self, playerImageTable)
 | 
			
		||||
 | 
			
		||||
    self:addState("run", 8,14, {tickStep = 2})
 | 
			
		||||
    self:addState("up", 1,7, {tickStep = 6})
 | 
			
		||||
    self:addState("down", 1,7, {tickStep = 6})
 | 
			
		||||
    self:addState("boom", 15,21, {tickStep = 10, loop = false})
 | 
			
		||||
 | 
			
		||||
    self:setDefaultState("down")
 | 
			
		||||
 | 
			
		||||
    self:playAnimation()
 | 
			
		||||
 | 
			
		||||
    -- Sprite properties
 | 
			
		||||
    self:moveTo(x, y)
 | 
			
		||||
    self:setZIndex(10)
 | 
			
		||||
    self:setCollideRect(3, 19, 63, 33)
 | 
			
		||||
 | 
			
		||||
    self:setTag(1)
 | 
			
		||||
 | 
			
		||||
    self:changeState("down")
 | 
			
		||||
 | 
			
		||||
    -- Physics properties
 | 
			
		||||
    self.xVelocity = 0
 | 
			
		||||
    self.yVelocity = 0
 | 
			
		||||
    self.maxXSpeed = 2
 | 
			
		||||
    self.maxYSpeed = 5
 | 
			
		||||
 | 
			
		||||
    self.fallSpeed = 0.4
 | 
			
		||||
 | 
			
		||||
    -- Player State
 | 
			
		||||
    self.touchingGround = false
 | 
			
		||||
    self.touchingCeiling = false
 | 
			
		||||
    self.touchingWall = false
 | 
			
		||||
    Player.dead = false
 | 
			
		||||
 | 
			
		||||
    Player.bat = 10000
 | 
			
		||||
 | 
			
		||||
    Player.dischargeRate = 1
 | 
			
		||||
 | 
			
		||||
    self.cantDown = false
 | 
			
		||||
 | 
			
		||||
    Player.moveRight = false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Player:handleGroundInput(state)
 | 
			
		||||
    if Player.bat <= 0 or Player.dead then
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local change, acceleratedChange = playdate.getCrankChange()
 | 
			
		||||
 | 
			
		||||
    if pd.buttonJustReleased(pd.kButtonLeft) or pd.buttonJustReleased(pd.kButtonRight) then
 | 
			
		||||
        self.cantDown = false
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if pd.buttonIsPressed(pd.kButtonLeft) then
 | 
			
		||||
        self:changeToRunState("left")
 | 
			
		||||
        self.cantDown = true
 | 
			
		||||
        Player.moveRight = false
 | 
			
		||||
    elseif pd.buttonIsPressed(pd.kButtonRight) then
 | 
			
		||||
        self:changeToRunState("right")
 | 
			
		||||
        self.cantDown = true
 | 
			
		||||
        Player.moveRight = true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if change ~= 0 then
 | 
			
		||||
        local force = 0.01
 | 
			
		||||
        if change > 0 then
 | 
			
		||||
            self:changeState("up")
 | 
			
		||||
        else
 | 
			
		||||
            self:changeState("down")
 | 
			
		||||
            force = 0.05
 | 
			
		||||
        end
 | 
			
		||||
        self.yVelocity = self.yVelocity - acceleratedChange * force
 | 
			
		||||
    elseif self.cantDown == false then
 | 
			
		||||
        self.cantDown = false
 | 
			
		||||
        self:changeToDownState()
 | 
			
		||||
    else
 | 
			
		||||
        self.yVelocity = self.fallSpeed 
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Player:changeToDownState()
 | 
			
		||||
    Player.moveRight = false
 | 
			
		||||
    self.yVelocity = self.fallSpeed
 | 
			
		||||
    self.xVelocity = 0
 | 
			
		||||
    self:changeState("down")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Player:changeToRunState(direction)
 | 
			
		||||
    if direction == "left" then
 | 
			
		||||
        self.xVelocity = -self.maxXSpeed
 | 
			
		||||
        self.globalFlip = 1
 | 
			
		||||
        self:changeState("run")
 | 
			
		||||
    elseif direction == "right" then
 | 
			
		||||
        self.xVelocity = self.maxXSpeed
 | 
			
		||||
        self.globalFlip = 0
 | 
			
		||||
        self:changeState("run")
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Player:handleMovementAndCollisions()
 | 
			
		||||
    local _, _, collisions, length = self:moveWithCollisions(self.x + self.xVelocity, self.y + self.yVelocity)
 | 
			
		||||
 | 
			
		||||
    self.touchingGround = false
 | 
			
		||||
    self.touchingCeiling = false
 | 
			
		||||
    self.touchingWall = false
 | 
			
		||||
 | 
			
		||||
    for i=1,length do
 | 
			
		||||
        local collision = collisions[i]
 | 
			
		||||
        local collisionType = collision.type
 | 
			
		||||
        local collisionObject = collision.other
 | 
			
		||||
        local collisionTag = collisionObject:getTag()
 | 
			
		||||
        if collisionType == gfx.sprite.kCollisionTypeSlide then
 | 
			
		||||
            if collision.normal.y == -1 then
 | 
			
		||||
                self.touchingGround = true
 | 
			
		||||
            elseif collision.normal.y == 1 then
 | 
			
		||||
                self.touchingCeiling = true
 | 
			
		||||
            end
 | 
			
		||||
 | 
			
		||||
            if collision.normal.x ~= 0 then
 | 
			
		||||
                self.touchingWall = true
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if collisionTag == 3 then
 | 
			
		||||
            Player.dead = true
 | 
			
		||||
            self:changeState("boom")
 | 
			
		||||
        -- elseif collisionTag == TAGS.Pickup then
 | 
			
		||||
        --     collisionObject:pickUp(self)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Player:isMovingRight()
 | 
			
		||||
    return Player.moveRight
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Player:isDead()
 | 
			
		||||
    return Player.dead
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Player:getBat()
 | 
			
		||||
    return Player.bat
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Player:handleDischarge(state)
 | 
			
		||||
    if Player.dead then
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
    if Player.bat <= 0 then
 | 
			
		||||
        Player.bat = 0
 | 
			
		||||
        self.fallSpeed = 2
 | 
			
		||||
        self:changeToDownState()
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    if state == "run" then
 | 
			
		||||
        Player.dischargeRate = 5
 | 
			
		||||
    elseif state == "up" then
 | 
			
		||||
        Player.dischargeRate = 10
 | 
			
		||||
    else
 | 
			
		||||
        Player.dischargeRate = 1
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    Player.bat = Player.bat - Player.dischargeRate
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Player:update()
 | 
			
		||||
    self:updateAnimation()
 | 
			
		||||
    if Player.dead then
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local state = self:getCurrentState()["name"]
 | 
			
		||||
 | 
			
		||||
    self:handleDischarge(state)
 | 
			
		||||
    self:handleGroundInput(state)
 | 
			
		||||
 | 
			
		||||
    self:handleMovementAndCollisions()
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								source/sprites/bg.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/sprites/bg.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 2.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								source/sprites/groundDbg.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/sprites/groundDbg.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 3.1 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								source/sprites/groundFin.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/sprites/groundFin.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 2.6 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								source/sprites/player-table-64-64.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/sprites/player-table-64-64.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 4.6 KiB  | 
		Reference in New Issue
	
	Block a user