Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60dfebcd0c | ||
|
|
05a96184e4 | ||
|
|
5b46515e5b | ||
|
|
f40b4df571 | ||
|
|
85a5f7d9df | ||
|
|
274455885d | ||
|
|
c4bbf48e0f | ||
|
|
638eac7ebe | ||
|
|
fb6434b8ad | ||
|
|
ff649ae863 | ||
|
|
c48f957920 | ||
|
|
050f4000fb | ||
|
|
d306ee9ec3 | ||
|
|
1ed64e3fda | ||
|
|
433923bdbd | ||
|
|
87ec99dd1e | ||
|
|
9b91dc1b80 | ||
|
|
a9fdf2510a | ||
|
|
79ccb61cfb | ||
|
|
0a4273bd1a | ||
|
|
4e04e5071b | ||
|
|
48a9b8ce84 | ||
|
|
a71abb5772 | ||
|
|
9feb12a5a1 | ||
|
|
ca3ce1a659 | ||
|
|
065b775e08 | ||
|
|
e76d11a5e6 | ||
|
|
eed73b744b | ||
|
|
cf7b871c56 | ||
|
|
054e9f4bf9 | ||
|
|
a3b99638af | ||
|
|
6cf7267078 | ||
|
|
e6a219c8cc | ||
|
|
9ccf971e58 | ||
|
|
2fcc73e387 | ||
|
|
589db1f26b | ||
|
|
f3f91a1d8e | ||
|
|
d93ed6c7db | ||
|
|
65de93f679 | ||
|
|
b8701fa703 | ||
|
|
62a59a74d7 | ||
|
|
92157c03e9 | ||
|
|
7fefeb61e7 | ||
|
|
b425be302a | ||
|
|
f30f6e646c | ||
|
|
0af3ab700d | ||
|
|
8248843722 | ||
|
|
5fa4bc458e | ||
|
|
40cce24b78 | ||
|
|
968a001a36 | ||
|
|
180f6b2cfa | ||
|
|
46fe5a5645 | ||
|
|
ad51619b4d | ||
|
|
90270b4a3d | ||
|
|
e98212b1cd | ||
|
|
bf78c62384 | ||
|
|
ddd42ca004 |
@@ -1,13 +1,54 @@
|
||||
# Changelog
|
||||
All notable changes will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.2.2] - 2020-11-20
|
||||
### Added
|
||||
- 32bit support
|
||||
- Controller (dancepads) support
|
||||
- Pause screen
|
||||
- Main Menu overhaul
|
||||
- Cool intro screen thing
|
||||
- Music playing on the freeplay menu.
|
||||
- UI sounds on freeplay menu
|
||||
- Score now shows mid-song.
|
||||
- Menu on pause screen! Can resume, and restart song, or go back to main menu.
|
||||
- New music made for pause menu!
|
||||
|
||||
### Changed
|
||||
- Moved all the intro texts to its own txt file instead of being hardcoded, this allows for much easier customization. File is in the data folder, called "introText.txt", follow the format in there and you're probably good to go!
|
||||
### Fixed
|
||||
- Fixed soft lock when pausing on song finish ([shoutouts gedehari](https://github.com/ninjamuffin99/Funkin/issues/15))
|
||||
- Think I fixed issue that led to in-game scores being off by 2 ([shoutouts Mike](https://github.com/ninjamuffin99/Funkin/issues/4))
|
||||
- Should have fixed the 1 frame note appearance thing. ([shoutouts Mike](https://github.com/ninjamuffin99/Funkin/issues/6))
|
||||
- Cleaned up some charting on South on hard mode
|
||||
- Fixed some animation timings, should feel both better to play, and watch. (shoutouts Dave/Ivan lol)
|
||||
- Animation issue where GF would freak out on the title screen if you returned to it([shoutouts MultiXIII](https://github.com/ninjamuffin99/Funkin/issues/12)).
|
||||
|
||||
## [0.2.1.2] - 2020-11-06
|
||||
### Fixed
|
||||
- Story mode scores not properly resetting, leading to VERY inflated highscores on the leaderboards. This also requires me to clear the scores that are on the leaderboard right now, sorry!
|
||||
- Difficulty on storymode and in freeplay scores
|
||||
- Hard mode difficulty on campaign levels have been fixed
|
||||
## [0.2.1.1] - 2020-11-06
|
||||
### Fixed
|
||||
- Week 2 not unlocking properly
|
||||
|
||||
## [0.2.1] - 2020-11-06
|
||||
### Added
|
||||
- Scores to the freeplay menu
|
||||
- A few new intro boot messages.
|
||||
- Lightning effect in Spooky stages
|
||||
- Campaign scores, can now compete on scoreboards for campaign!
|
||||
- Can now change difficulties in Freeplay mode
|
||||
|
||||
### Changed
|
||||
- Balanced out Normal mode for the harder songs(Dadbattle and Spookeez, not South yet). Should be much easier all around.
|
||||
- Put tutorial in it's own 'week', so that if you want to play week 1, you don't have to play the tutorial.
|
||||
|
||||
### Fixed
|
||||
- One of the charting bits on South and Spookeez during the intro.
|
||||
|
||||
## [0.2.0] - 2020-11-01
|
||||
### Added
|
||||
- Uhh Newgrounds release lolol I always lose track of shit.
|
||||
|
||||
## [0.1.0] - 2020-10-05
|
||||
### Added
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<project>
|
||||
<!-- _________________________ Application Settings _________________________ -->
|
||||
|
||||
<app title="Friday Night Funkin" file="Funkin" main="Main" version="0.0.1" company="HaxeFlixel" />
|
||||
<app title="Friday Night Funkin" file="Funkin" packageName="com.ninjamuffin99.funkin" main="Main" version="0.2.2" company="ninjamuffin99" />
|
||||
|
||||
<!--The flixel preloader is not accurate in Chrome. You can use it regularly if you embed the swf into a html file
|
||||
or you can set the actual size of your file manually at "FlxPreloaderBase-onUpdate-bytesTotal"-->
|
||||
@@ -25,6 +25,9 @@
|
||||
<!--Mobile-specific-->
|
||||
<window if="mobile" orientation="landscape" fullscreen="true" width="0" height="0" />
|
||||
|
||||
<!--Switch-specific-->
|
||||
<window if="switch" orientation="landscape" fullscreen="true" width="0" height="0" resizable="true" />
|
||||
|
||||
<!-- _____________________________ Path Settings ____________________________ -->
|
||||
|
||||
<set name="BUILD_DIR" value="export/debug" if="debug" />
|
||||
@@ -36,11 +39,15 @@
|
||||
<assets path="assets/images"/>
|
||||
<assets path="assets/data"/>
|
||||
|
||||
<assets path="assets/music" include="*.mp3" if="web" />
|
||||
<assets path="assets/music" include="*.ogg" unless="web" />
|
||||
<!-- <library name="noPreload" preload='false'/> -->
|
||||
<!-- <library name="noPreload"/> -->
|
||||
<assets path="assets/music" include="*.mp3" if="web"/>
|
||||
<assets path="assets/music" include="*.ogg" unless="web"/>
|
||||
<assets path="assets/sounds" include="*.mp3" if="web" />
|
||||
<assets path="assets/sounds" include="*.ogg" unless="web" />
|
||||
|
||||
<assets path="CHANGELOG.md"/>
|
||||
|
||||
<assets path="assets/fonts/vcr.ttf" embed="true" />
|
||||
|
||||
|
||||
@@ -54,6 +61,9 @@
|
||||
|
||||
<!--In case you want to use the ui package-->
|
||||
<haxelib name="flixel-ui" />
|
||||
<haxelib name="newgrounds" />
|
||||
<!-- <haxelib name="markdown" /> -->
|
||||
<!-- <haxelib name="HtmlParser" /> -->
|
||||
|
||||
<!--In case you want to use nape with flixel-->
|
||||
<!--<haxelib name="nape-haxe4" />-->
|
||||
@@ -93,7 +103,10 @@
|
||||
<!-- _________________________________ Custom _______________________________ -->
|
||||
|
||||
<!--Place custom nodes like icons here (higher priority to override the HaxeFlixel icon)-->
|
||||
<icon path="art/icon.png"/>
|
||||
|
||||
<icon path="art/icon.png" />
|
||||
<!-- <haxedef name="SKIP_TO_PLAYSTATE" if="debug" /> -->
|
||||
<!-- <haxedef name="NG_LOGIN" /> -->
|
||||
<haxedef name="NG_LOGIN" if="newgrounds" />
|
||||
|
||||
|
||||
</project>
|
||||
|
||||
@@ -3,3 +3,4 @@
|
||||
This is the repository for Friday Night Funkin, a game originally made for Ludum Dare 47 "Stuck In a Loop".
|
||||
|
||||
Play the Ludum Dare prototype here: https://ninja-muffin24.itch.io/friday-night-funkin
|
||||
Play the Newgrounds one here: https://www.newgrounds.com/portal/view/770371
|
||||
|
||||
|
After Width: | Height: | Size: 3.0 MiB |
@@ -0,0 +1,11 @@
|
||||
@echo off
|
||||
color 0a
|
||||
cd ..
|
||||
@echo on
|
||||
echo BUILDING GAME
|
||||
lime build windows -debug
|
||||
echo UPLOADING 64 BIT VERSION TO ITCH
|
||||
butler push ./export/debug/windows/bin ninja-muffin24/funkin:windows-secretBeta
|
||||
butler status ninja-muffin24/funkin:windows-secretBeta
|
||||
echo ITCH SHIT UPDATED LMAOOOOO
|
||||
pause
|
||||
@@ -0,0 +1,27 @@
|
||||
@echo off
|
||||
cd ..
|
||||
@echo on
|
||||
echo REBUILDING LIME FOR EXPORT (VERBOSE)
|
||||
@echo off
|
||||
color 0b
|
||||
@echo on
|
||||
lime rebuild windows -clean -v
|
||||
@echo off
|
||||
color 0a
|
||||
@echo on
|
||||
lime rebuild switch -clean -v
|
||||
@echo off
|
||||
color 0e
|
||||
@echo on
|
||||
lime rebuild tools -clean -v
|
||||
echo HOPE AND PRAY...
|
||||
@echo off
|
||||
color 0a
|
||||
@echo on
|
||||
echo BUILDING GAME
|
||||
lime build switch -final -v
|
||||
@echo off
|
||||
color 0b
|
||||
@echo on
|
||||
echo NSP FILE CREATED
|
||||
pause
|
||||
|
After Width: | Height: | Size: 582 KiB |
@@ -0,0 +1,24 @@
|
||||
shoutouts to tom fulp--lmao
|
||||
Ludum dare--extraordinaire
|
||||
cyberzone--coming soon
|
||||
love to thriftman--swag
|
||||
ultimate rhythm gaming--probably
|
||||
dope ass game--playstation magazine
|
||||
in loving memory of--henryeyes
|
||||
dancin--forever
|
||||
funkin--forever
|
||||
ritz dx--rest in peace lol
|
||||
rate five--pls no blam
|
||||
rhythm gaming--ultimate
|
||||
game of the year--forever
|
||||
you already know--we really out here
|
||||
rise and grind--love to luis
|
||||
like parappa--but cooler
|
||||
album of the year--chuckie finster
|
||||
free gitaroo man--with love to wandaboy
|
||||
better than geometry dash--fight me robtop
|
||||
kiddbrute for president--vote now
|
||||
play dead estate--on newgrounds
|
||||
this is a god damn prototype--we workin on it okay
|
||||
women are real--this is official
|
||||
too over exposed--newgrounds cant handle us
|
||||
|
Before Width: | Height: | Size: 4.6 MiB After Width: | Height: | Size: 4.8 MiB |
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextureAtlas imagePath="BoyFriend_Assets.png">
|
||||
<TextureAtlas imagePath="BOYFRIEND.png">
|
||||
<!-- Created with Adobe Animate version 20.0.0.17400 -->
|
||||
<!-- http://www.adobe.com/products/animate.html -->
|
||||
<SubTexture name="BF Dead Loop0000" x="0" y="0" width="439" height="435"/>
|
||||
@@ -442,26 +442,60 @@
|
||||
<SubTexture name="BF idle dance0011" x="1669" y="2344" width="408" height="412" frameX="-2" frameY="0" frameWidth="411" frameHeight="412"/>
|
||||
<SubTexture name="BF idle dance0012" x="1669" y="2344" width="408" height="412" frameX="-2" frameY="0" frameWidth="411" frameHeight="412"/>
|
||||
<SubTexture name="BF idle dance0013" x="1669" y="2344" width="408" height="412" frameX="-2" frameY="0" frameWidth="411" frameHeight="412"/>
|
||||
<SubTexture name="boyfriend attack0000" x="2087" y="2344" width="697" height="597" frameX="0" frameY="-87" frameWidth="708" frameHeight="685"/>
|
||||
<SubTexture name="boyfriend attack0001" x="2087" y="2344" width="697" height="597" frameX="0" frameY="-87" frameWidth="708" frameHeight="685"/>
|
||||
<SubTexture name="boyfriend attack0002" x="2794" y="2344" width="603" height="660" frameX="-102" frameY="-24" frameWidth="708" frameHeight="685"/>
|
||||
<SubTexture name="boyfriend attack0003" x="2794" y="2344" width="603" height="660" frameX="-102" frameY="-24" frameWidth="708" frameHeight="685"/>
|
||||
<SubTexture name="boyfriend attack0004" x="3407" y="2344" width="444" height="684" frameX="-263" frameY="0" frameWidth="708" frameHeight="685"/>
|
||||
<SubTexture name="boyfriend attack0005" x="3407" y="2344" width="444" height="684" frameX="-263" frameY="0" frameWidth="708" frameHeight="685"/>
|
||||
<SubTexture name="boyfriend attack0006" x="3861" y="2344" width="501" height="630" frameX="-207" frameY="-55" frameWidth="708" frameHeight="685"/>
|
||||
<SubTexture name="boyfriend dodge0000" x="4372" y="2344" width="375" height="404" frameX="-3" frameY="0" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0001" x="4757" y="2344" width="375" height="404" frameX="-3" frameY="0" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0002" x="5142" y="2344" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0003" x="5532" y="2344" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0004" x="5922" y="2344" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0005" x="5142" y="2344" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0006" x="5532" y="2344" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0007" x="5922" y="2344" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0008" x="5142" y="2344" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0009" x="5532" y="2344" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0010" x="5922" y="2344" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0011" x="5142" y="2344" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0012" x="5532" y="2344" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0013" x="5922" y="2344" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0014" x="5142" y="2344" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="BF idle shaking0000" x="2087" y="2344" width="408" height="412" frameX="-1" frameY="-1" frameWidth="410" frameHeight="413"/>
|
||||
<SubTexture name="BF idle shaking0001" x="2505" y="2344" width="408" height="412" frameX="-2" frameY="-1" frameWidth="410" frameHeight="413"/>
|
||||
<SubTexture name="BF idle shaking0002" x="2923" y="2344" width="408" height="413" frameX="-1" frameY="0" frameWidth="410" frameHeight="413"/>
|
||||
<SubTexture name="BF idle shaking0003" x="3341" y="2344" width="410" height="413"/>
|
||||
<SubTexture name="bf pre attack0000" x="3761" y="2344" width="386" height="373" frameX="0" frameY="-1" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0001" x="3761" y="2344" width="386" height="373" frameX="0" frameY="-1" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0002" x="4157" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0003" x="4157" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0004" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0005" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0006" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0007" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0008" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0009" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0010" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0011" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0012" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0013" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0014" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0015" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0016" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0017" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0018" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0019" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0020" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0021" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0022" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0023" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0024" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0025" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0026" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0027" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0028" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="bf pre attack0029" x="4549" y="2344" width="382" height="374" frameX="-2" frameY="0" frameWidth="386" frameHeight="374"/>
|
||||
<SubTexture name="boyfriend attack0000" x="4941" y="2344" width="697" height="597" frameX="0" frameY="-87" frameWidth="708" frameHeight="685"/>
|
||||
<SubTexture name="boyfriend attack0001" x="4941" y="2344" width="697" height="597" frameX="0" frameY="-87" frameWidth="708" frameHeight="685"/>
|
||||
<SubTexture name="boyfriend attack0002" x="5648" y="2344" width="603" height="660" frameX="-102" frameY="-24" frameWidth="708" frameHeight="685"/>
|
||||
<SubTexture name="boyfriend attack0003" x="5648" y="2344" width="603" height="660" frameX="-102" frameY="-24" frameWidth="708" frameHeight="685"/>
|
||||
<SubTexture name="boyfriend attack0004" x="6261" y="2344" width="444" height="684" frameX="-263" frameY="0" frameWidth="708" frameHeight="685"/>
|
||||
<SubTexture name="boyfriend attack0005" x="6261" y="2344" width="444" height="684" frameX="-263" frameY="0" frameWidth="708" frameHeight="685"/>
|
||||
<SubTexture name="boyfriend attack0006" x="6715" y="2344" width="501" height="630" frameX="-207" frameY="-55" frameWidth="708" frameHeight="685"/>
|
||||
<SubTexture name="boyfriend dodge0000" x="7226" y="2344" width="375" height="404" frameX="-3" frameY="0" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0001" x="7611" y="2344" width="375" height="404" frameX="-3" frameY="0" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0002" x="0" y="3038" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0003" x="390" y="3038" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0004" x="780" y="3038" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0005" x="0" y="3038" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0006" x="390" y="3038" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0007" x="780" y="3038" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0008" x="0" y="3038" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0009" x="390" y="3038" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0010" x="780" y="3038" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0011" x="0" y="3038" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0012" x="390" y="3038" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0013" x="780" y="3038" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
<SubTexture name="boyfriend dodge0014" x="0" y="3038" width="380" height="403" frameX="0" frameY="-1" frameWidth="380" frameHeight="404"/>
|
||||
</TextureAtlas>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.1 MiB After Width: | Height: | Size: 3.3 MiB |
@@ -73,121 +73,125 @@
|
||||
<SubTexture name="GF Down Note0017" x="4971" y="1325" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Down Note0018" x="4971" y="1325" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Down Note0019" x="4971" y="1325" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0000" x="5680" y="1325" width="699" height="632" frameX="-2" frameY="-5" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0001" x="6389" y="1325" width="703" height="632" frameX="0" frameY="-5" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0002" x="7102" y="1325" width="703" height="637"/>
|
||||
<SubTexture name="GF Right Note0003" x="0" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0004" x="709" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0005" x="1418" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0006" x="2127" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0007" x="2127" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0008" x="2836" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0009" x="2836" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0010" x="2836" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0011" x="2836" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0012" x="2836" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0013" x="2836" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0014" x="2836" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Up Note0000" x="3545" y="1978" width="699" height="661" frameX="-2" frameY="0" frameWidth="703" frameHeight="661"/>
|
||||
<SubTexture name="GF Up Note0001" x="4254" y="1978" width="703" height="661"/>
|
||||
<SubTexture name="GF Up Note0002" x="4967" y="1978" width="703" height="661"/>
|
||||
<SubTexture name="GF Up Note0003" x="5680" y="1978" width="699" height="661" frameX="-2" frameY="0" frameWidth="703" frameHeight="661"/>
|
||||
<SubTexture name="GF Up Note0004" x="6389" y="1978" width="699" height="661" frameX="-2" frameY="0" frameWidth="703" frameHeight="661"/>
|
||||
<SubTexture name="GF Up Note0005" x="6389" y="1978" width="699" height="661" frameX="-2" frameY="0" frameWidth="703" frameHeight="661"/>
|
||||
<SubTexture name="GF Up Note0006" x="6389" y="1978" width="699" height="661" frameX="-2" frameY="0" frameWidth="703" frameHeight="661"/>
|
||||
<SubTexture name="GF left note0000" x="7098" y="1978" width="699" height="633" frameX="-2" frameY="-5" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0001" x="0" y="2649" width="703" height="631" frameX="0" frameY="-7" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0002" x="713" y="2649" width="703" height="638"/>
|
||||
<SubTexture name="GF left note0003" x="1426" y="2649" width="699" height="638" frameX="-2" frameY="0" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0004" x="2135" y="2649" width="699" height="638" frameX="-2" frameY="0" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0005" x="2844" y="2649" width="699" height="638" frameX="-2" frameY="0" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0006" x="3553" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0007" x="3553" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0008" x="4262" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0009" x="4262" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0010" x="4262" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0011" x="4262" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0012" x="4262" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0013" x="4262" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0014" x="4262" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="gf sad0000" x="4971" y="2649" width="699" height="633" frameX="0" frameY="-3" frameWidth="699" frameHeight="636"/>
|
||||
<SubTexture name="gf sad0001" x="4971" y="2649" width="699" height="633" frameX="0" frameY="-3" frameWidth="699" frameHeight="636"/>
|
||||
<SubTexture name="gf sad0002" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0003" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0004" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0005" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0006" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0007" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0008" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0009" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0010" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0011" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0012" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0013" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0014" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0015" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0016" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0017" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0018" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0019" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0020" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0021" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0022" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0023" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0024" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0025" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0026" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0027" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0028" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0029" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0030" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0031" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0032" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0033" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0034" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0035" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0036" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0037" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0038" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0039" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0040" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0041" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0042" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0043" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0044" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0045" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0046" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0047" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0048" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0049" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0050" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0051" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0052" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0053" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0054" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0055" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0056" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0057" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0058" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0059" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0060" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0061" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0062" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0063" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0064" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0065" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0066" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0067" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0068" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0069" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0070" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0071" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0072" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0073" x="0" y="3297" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0074" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0075" x="5680" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0076" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0077" x="6389" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0078" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0079" x="7098" y="2649" width="699" height="636"/>
|
||||
<SubTexture name="GF FEAR 0000" x="5680" y="1325" width="699" height="640"/>
|
||||
<SubTexture name="GF FEAR 0001" x="6389" y="1325" width="699" height="640"/>
|
||||
<SubTexture name="GF FEAR 0002" x="7098" y="1325" width="699" height="638" frameX="0" frameY="-2" frameWidth="699" frameHeight="640"/>
|
||||
<SubTexture name="GF FEAR 0003" x="0" y="1978" width="699" height="640"/>
|
||||
<SubTexture name="GF Right Note0000" x="709" y="1978" width="699" height="632" frameX="-2" frameY="-5" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0001" x="1418" y="1978" width="703" height="632" frameX="0" frameY="-5" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0002" x="2131" y="1978" width="703" height="637"/>
|
||||
<SubTexture name="GF Right Note0003" x="2844" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0004" x="3553" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0005" x="4262" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0006" x="4971" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0007" x="4971" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0008" x="5680" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0009" x="5680" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0010" x="5680" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0011" x="5680" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0012" x="5680" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0013" x="5680" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Right Note0014" x="5680" y="1978" width="699" height="637" frameX="-2" frameY="0" frameWidth="703" frameHeight="637"/>
|
||||
<SubTexture name="GF Up Note0000" x="6389" y="1978" width="699" height="661" frameX="-2" frameY="0" frameWidth="703" frameHeight="661"/>
|
||||
<SubTexture name="GF Up Note0001" x="7098" y="1978" width="703" height="661"/>
|
||||
<SubTexture name="GF Up Note0002" x="0" y="2649" width="703" height="661"/>
|
||||
<SubTexture name="GF Up Note0003" x="713" y="2649" width="699" height="661" frameX="-2" frameY="0" frameWidth="703" frameHeight="661"/>
|
||||
<SubTexture name="GF Up Note0004" x="1422" y="2649" width="699" height="661" frameX="-2" frameY="0" frameWidth="703" frameHeight="661"/>
|
||||
<SubTexture name="GF Up Note0005" x="1422" y="2649" width="699" height="661" frameX="-2" frameY="0" frameWidth="703" frameHeight="661"/>
|
||||
<SubTexture name="GF Up Note0006" x="1422" y="2649" width="699" height="661" frameX="-2" frameY="0" frameWidth="703" frameHeight="661"/>
|
||||
<SubTexture name="GF left note0000" x="2131" y="2649" width="699" height="633" frameX="-2" frameY="-5" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0001" x="2840" y="2649" width="703" height="631" frameX="0" frameY="-7" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0002" x="3553" y="2649" width="703" height="638"/>
|
||||
<SubTexture name="GF left note0003" x="4266" y="2649" width="699" height="638" frameX="-2" frameY="0" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0004" x="4975" y="2649" width="699" height="638" frameX="-2" frameY="0" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0005" x="5684" y="2649" width="699" height="638" frameX="-2" frameY="0" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0006" x="6393" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0007" x="6393" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0008" x="7102" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0009" x="7102" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0010" x="7102" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0011" x="7102" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0012" x="7102" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0013" x="7102" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="GF left note0014" x="7102" y="2649" width="699" height="637" frameX="-2" frameY="-1" frameWidth="703" frameHeight="638"/>
|
||||
<SubTexture name="gf sad0000" x="0" y="3320" width="699" height="633" frameX="0" frameY="-3" frameWidth="699" frameHeight="636"/>
|
||||
<SubTexture name="gf sad0001" x="0" y="3320" width="699" height="633" frameX="0" frameY="-3" frameWidth="699" frameHeight="636"/>
|
||||
<SubTexture name="gf sad0002" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0003" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0004" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0005" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0006" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0007" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0008" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0009" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0010" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0011" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0012" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0013" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0014" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0015" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0016" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0017" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0018" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0019" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0020" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0021" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0022" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0023" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0024" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0025" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0026" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0027" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0028" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0029" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0030" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0031" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0032" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0033" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0034" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0035" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0036" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0037" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0038" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0039" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0040" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0041" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0042" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0043" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0044" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0045" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0046" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0047" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0048" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0049" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0050" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0051" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0052" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0053" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0054" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0055" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0056" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0057" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0058" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0059" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0060" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0061" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0062" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0063" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0064" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0065" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0066" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0067" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0068" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0069" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0070" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0071" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0072" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0073" x="2836" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0074" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0075" x="709" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0076" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0077" x="1418" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0078" x="2127" y="3320" width="699" height="636"/>
|
||||
<SubTexture name="gf sad0079" x="2127" y="3320" width="699" height="636"/>
|
||||
</TextureAtlas>
|
||||
|
||||
|
After Width: | Height: | Size: 264 KiB |
|
After Width: | Height: | Size: 42 KiB |
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextureAtlas imagePath="backspace.png">
|
||||
<!-- Created with Adobe Animate version 20.0.0.17400 -->
|
||||
<!-- http://www.adobe.com/products/animate.html -->
|
||||
<SubTexture name="backspace PRESSED0000" x="0" y="0" width="288" height="160" frameX="-14" frameY="-6" frameWidth="314" frameHeight="174"/>
|
||||
<SubTexture name="backspace PRESSED0001" x="0" y="0" width="288" height="160" frameX="-14" frameY="-6" frameWidth="314" frameHeight="174"/>
|
||||
<SubTexture name="backspace PRESSED0002" x="298" y="0" width="314" height="174"/>
|
||||
<SubTexture name="backspace to exit0000" x="622" y="0" width="280" height="106"/>
|
||||
<SubTexture name="backspace to exit white0000" x="0" y="184" width="280" height="106"/>
|
||||
</TextureAtlas>
|
||||
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
@@ -5,19 +5,18 @@
|
||||
<SubTexture name="EASY0000" x="0" y="0" width="196" height="65"/>
|
||||
<SubTexture name="HARD0000" x="206" y="0" width="211" height="67"/>
|
||||
<SubTexture name="NORMAL0000" x="427" y="0" width="308" height="67"/>
|
||||
<SubTexture name="WEEK10000" x="0" y="77" width="360" height="89"/>
|
||||
<SubTexture name="WEEK1 select0000" x="0" y="77" width="360" height="89"/>
|
||||
<SubTexture name="WEEK1 select0001" x="370" y="77" width="360" height="89"/>
|
||||
<SubTexture name="WEEK20000" x="0" y="279" width="361" height="87"/>
|
||||
<SubTexture name="arrow left0000" x="740" y="77" width="48" height="85"/>
|
||||
<SubTexture name="arrow push left0000" x="798" y="77" width="42" height="75"/>
|
||||
<SubTexture name="arrow push right0000" x="850" y="77" width="41" height="74"/>
|
||||
<SubTexture name="arrow right0000" x="901" y="77" width="47" height="85"/>
|
||||
<SubTexture name="lock0000" x="0" y="176" width="67" height="93"/>
|
||||
<SubTexture name="week 2 CANNOT select0000" x="77" y="176" width="361" height="87" frameX="-10" frameY="0" frameWidth="383" frameHeight="87"/>
|
||||
<SubTexture name="week 2 CANNOT select0001" x="448" y="176" width="361" height="87" frameX="0" frameY="0" frameWidth="383" frameHeight="87"/>
|
||||
<SubTexture name="week 2 CANNOT select0002" x="0" y="279" width="362" height="87" frameX="-21" frameY="0" frameWidth="383" frameHeight="87"/>
|
||||
<SubTexture name="week 2 CANNOT select0003" x="448" y="176" width="361" height="87" frameX="-7" frameY="0" frameWidth="383" frameHeight="87"/>
|
||||
<SubTexture name="week 2 CANNOT select0004" x="77" y="176" width="361" height="87" frameX="-11" frameY="0" frameWidth="383" frameHeight="87"/>
|
||||
<SubTexture name="week 2 CANNOT select0005" x="77" y="176" width="361" height="87" frameX="-11" frameY="0" frameWidth="383" frameHeight="87"/>
|
||||
<SubTexture name="week2 select0000" x="77" y="176" width="361" height="87" frameX="0" frameY="0" frameWidth="383" frameHeight="87"/>
|
||||
<SubTexture name="week2 select0001" x="372" y="279" width="361" height="87"/>
|
||||
<SubTexture name="tutorial0000" x="77" y="176" width="443" height="82"/>
|
||||
<SubTexture name="tutorial selected0000" x="77" y="176" width="443" height="82"/>
|
||||
<SubTexture name="tutorial selected0001" x="530" y="176" width="443" height="82"/>
|
||||
<SubTexture name="week2 select0000" x="0" y="279" width="361" height="87"/>
|
||||
<SubTexture name="week2 select0001" x="371" y="279" width="361" height="87"/>
|
||||
</TextureAtlas>
|
||||
|
||||
|
After Width: | Height: | Size: 350 KiB |
|
After Width: | Height: | Size: 232 KiB |
@@ -13,8 +13,9 @@
|
||||
<title>Friday Night Funkin'</title>
|
||||
<meta name="description" content="A dope ass rhythm game">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<!-- <link href="website/styles.css" rel="stylesheet" type="text/css"> -->
|
||||
<link href="styles.css" rel="stylesheet" type="text/css">
|
||||
<!-- <link href="website/mm.ico" rel="icon" type="image/x-icon"> -->
|
||||
<link rel="shortcut icon" type="image/png" href="../art/icon.png" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -22,13 +23,38 @@
|
||||
<header>
|
||||
</header>
|
||||
|
||||
<marquee width="600" style="width: 800px;">Friday Night Funkin</marquee>
|
||||
|
||||
<marquee width="1920" scrollamount="2" scrolldelay="10" truespeed="truespeed">Friday Night Funkin</marquee>
|
||||
<!--Hot tortilla wrap-->
|
||||
<div id="wrapper">
|
||||
<!--Itch Widget-->
|
||||
<h1>Friday Night Funkin the video game</h1>
|
||||
<iframe src="https://itch.io/embed/775903?linkback=true&bg_color=000000&fg_color=ffffff&link_color=6454f8&border_color=333333" width="552" height="167" frameborder="0"><a href="https://ninja-muffin24.itch.io/friday-night-funkin">Friday Night Funkin' (Ludum Dare Prototype) by ninjamuffin99</a></iframe>
|
||||
<h1>Friday Night Funkin' - Rhythm game extraordinaire</h1>
|
||||
|
||||
|
||||
<div id="coolervidwrapper">
|
||||
<div class='videoWrapper'>
|
||||
<iframe width="560" height="349" src="https://www.youtube.com/embed/HMNKUo3CCpU" frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowfullscreen></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="coolBox hovertext" id="twitter">
|
||||
<p class="description">Friday Night Funkin' is a dope ass rhythm game.</p>
|
||||
<p class='description'>It is made by <a href="https://twitter.com/ninja_muffin99">ninjamuffin99 (programmer)</a>, <a
|
||||
href="https://twitter.com/PhantomArcade3K">PhantomArcade (animator)</a>, <a
|
||||
href="https://twitter.com/evilsk8r">evilsk8r (artist)</a>,
|
||||
and <a href="https://twitter.com/kawaisprite">Kawaisprite (musician)</a> originally for Ludum Dare 47.</p>
|
||||
</div>
|
||||
|
||||
<div class="linktext hovertext" id="ng">
|
||||
<a href="https://www.newgrounds.com/portal/view/770371">Play demo on Newgrounds</a>
|
||||
</div>
|
||||
|
||||
<div class='linktext hovertext' id="itch">
|
||||
<a href="https://ninja-muffin24.itch.io/funkin">Support the game on Itch.io</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,97 @@
|
||||
.coolBox {
|
||||
background: #1a1a1aCC;
|
||||
margin: 40px 4vw;
|
||||
padding: 25px;
|
||||
font-size: 120%;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
#wrapper
|
||||
{
|
||||
padding: 20px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
marquee {
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
body {
|
||||
background-image: url('img/skin-funkin-cardbordtoast.jpg');
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-size: cover;
|
||||
color:white;
|
||||
background-color: #000;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
|
||||
}
|
||||
|
||||
a { color:inherit;
|
||||
text-decoration: none;}
|
||||
|
||||
|
||||
.hovertext a{
|
||||
color:white;
|
||||
text-shadow: 0px 0px #00000077;
|
||||
transition: color 1s, text-shadow 1s;
|
||||
}
|
||||
|
||||
.hovertext a:hover
|
||||
{
|
||||
text-shadow: 2px 2px #00000077;
|
||||
color: #ffb50e;
|
||||
}
|
||||
|
||||
.linktext {
|
||||
text-align: center;
|
||||
display:block;
|
||||
font-size: 130%;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.linktext a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.linktext a:hover {
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#itch a:hover
|
||||
{
|
||||
color: #fa5c5c;
|
||||
}
|
||||
#twitter a:hover
|
||||
{
|
||||
color: #00acee;
|
||||
}
|
||||
|
||||
|
||||
#coolervidwrapper {
|
||||
padding-left: min(12em, 75%);
|
||||
padding-right: min(12em, 75%);
|
||||
min-width: 30%;
|
||||
}
|
||||
|
||||
.videoWrapper {
|
||||
position: relative;
|
||||
padding-bottom: 56.25%; /* 16:9 */
|
||||
height: 0;
|
||||
|
||||
max-block-size: 1400px;
|
||||
}
|
||||
.videoWrapper iframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
}
|
||||
@@ -48,6 +48,7 @@ class Alphabet extends FlxSpriteGroup
|
||||
this.text = text;
|
||||
isBold = bold;
|
||||
|
||||
|
||||
if (text != "")
|
||||
{
|
||||
if (typed)
|
||||
@@ -77,7 +78,8 @@ class Alphabet extends FlxSpriteGroup
|
||||
lastWasSpace = true;
|
||||
}
|
||||
|
||||
if (AlphaCharacter.alphabet.contains(character.toLowerCase()))
|
||||
if (AlphaCharacter.alphabet.indexOf(character.toLowerCase()) != -1)
|
||||
//if (AlphaCharacter.alphabet.contains(character.toLowerCase()))
|
||||
{
|
||||
if (lastSprite != null)
|
||||
{
|
||||
@@ -121,6 +123,7 @@ class Alphabet extends FlxSpriteGroup
|
||||
_finalText = text;
|
||||
doSplitWords();
|
||||
|
||||
|
||||
// trace(arrayShit);
|
||||
|
||||
var loopNum:Int = 0;
|
||||
@@ -137,6 +140,7 @@ class Alphabet extends FlxSpriteGroup
|
||||
xPosResetted = true;
|
||||
xPos = 0;
|
||||
curRow += 1;
|
||||
|
||||
}
|
||||
|
||||
if (splitWords[loopNum] == " ")
|
||||
@@ -144,9 +148,17 @@ class Alphabet extends FlxSpriteGroup
|
||||
lastWasSpace = true;
|
||||
}
|
||||
|
||||
#if (haxe >= "4.0.0")
|
||||
var isNumber:Bool = AlphaCharacter.numbers.contains(splitWords[loopNum]);
|
||||
var isSymbol:Bool = AlphaCharacter.symbols.contains(splitWords[loopNum]);
|
||||
if (AlphaCharacter.alphabet.contains(splitWords[loopNum].toLowerCase()) || isNumber || isSymbol)
|
||||
#else
|
||||
var isNumber:Bool = AlphaCharacter.numbers.indexOf(splitWords[loopNum]) != -1;
|
||||
var isSymbol:Bool = AlphaCharacter.symbols.indexOf(splitWords[loopNum]) != -1;
|
||||
#end
|
||||
|
||||
if (AlphaCharacter.alphabet.indexOf(splitWords[loopNum].toLowerCase()) != -1 || isNumber || isSymbol)
|
||||
//if (AlphaCharacter.alphabet.contains(splitWords[loopNum].toLowerCase()) || isNumber || isSymbol)
|
||||
|
||||
{
|
||||
if (lastSprite != null && !xPosResetted)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ package;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.util.FlxTimer;
|
||||
|
||||
using StringTools;
|
||||
|
||||
@@ -30,6 +31,8 @@ class Boyfriend extends Character
|
||||
animation.addByPrefix('firstDeath', "BF dies", 24, false);
|
||||
animation.addByPrefix('deathLoop', "BF Dead Loop", 24, true);
|
||||
animation.addByPrefix('deathConfirm', "BF Dead confirm", 24, false);
|
||||
|
||||
animation.addByPrefix('scared', 'BF idle shaking', 24);
|
||||
playAnim('idle');
|
||||
|
||||
antialiasing = true;
|
||||
@@ -47,10 +50,18 @@ class Boyfriend extends Character
|
||||
addOffset('firstDeath', 37, 11);
|
||||
addOffset('deathLoop', 37, 5);
|
||||
addOffset('deathConfirm', 37, 69);
|
||||
addOffset('scared', -4);
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (animation.curAnim.name.startsWith('sing'))
|
||||
{
|
||||
holdTimer += elapsed;
|
||||
}
|
||||
else
|
||||
holdTimer = 0;
|
||||
|
||||
if (animation.curAnim.name.endsWith('miss') && animation.curAnim.finished && !debugMode)
|
||||
{
|
||||
playAnim('idle', true, false, 10);
|
||||
|
||||
@@ -3,6 +3,8 @@ package;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class Character extends FlxSprite
|
||||
{
|
||||
public var animOffsets:Map<String, Array<Dynamic>>;
|
||||
@@ -11,6 +13,8 @@ class Character extends FlxSprite
|
||||
public var isPlayer:Bool = false;
|
||||
public var curCharacter:String = 'bf';
|
||||
|
||||
public var holdTimer:Float = 0;
|
||||
|
||||
public function new(x:Float, y:Float, ?character:String = "bf", ?isPlayer:Bool = false)
|
||||
{
|
||||
animOffsets = new Map<String, Array<Dynamic>>();
|
||||
@@ -24,7 +28,6 @@ class Character extends FlxSprite
|
||||
|
||||
switch (curCharacter)
|
||||
{
|
||||
case 'bf':
|
||||
case 'gf':
|
||||
// GIRLFRIEND CODE
|
||||
tex = FlxAtlasFrames.fromSparrow(AssetPaths.GF_assets__png, AssetPaths.GF_assets__xml);
|
||||
@@ -38,6 +41,8 @@ class Character extends FlxSprite
|
||||
animation.addByIndices('danceLeft', 'GF Dancing Beat', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
|
||||
animation.addByIndices('danceRight', 'GF Dancing Beat', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
|
||||
|
||||
animation.addByPrefix('scared', 'GF FEAR', 24);
|
||||
|
||||
addOffset('cheer');
|
||||
addOffset('sad', -2, -2);
|
||||
addOffset('danceLeft', 0, -9);
|
||||
@@ -48,6 +53,8 @@ class Character extends FlxSprite
|
||||
addOffset("singLEFT", 0, -19);
|
||||
addOffset("singDOWN", 0, -20);
|
||||
|
||||
addOffset('scared');
|
||||
|
||||
playAnim('danceRight');
|
||||
|
||||
case 'dad':
|
||||
@@ -103,6 +110,29 @@ class Character extends FlxSprite
|
||||
}
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (curCharacter != 'bf')
|
||||
{
|
||||
if (animation.curAnim.name.startsWith('sing'))
|
||||
{
|
||||
holdTimer += elapsed;
|
||||
}
|
||||
|
||||
var dadVar:Float = 4;
|
||||
|
||||
if (curCharacter == 'dad')
|
||||
dadVar = 6.1;
|
||||
if (holdTimer >= Conductor.stepCrochet * dadVar * 0.001)
|
||||
{
|
||||
dance();
|
||||
holdTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
private var danced:Bool = false;
|
||||
|
||||
/**
|
||||
@@ -112,6 +142,8 @@ class Character extends FlxSprite
|
||||
{
|
||||
switch (curCharacter)
|
||||
{
|
||||
case 'bf':
|
||||
|
||||
case 'gf':
|
||||
danced = !danced;
|
||||
|
||||
|
||||
@@ -28,7 +28,9 @@ import openfl.events.Event;
|
||||
import openfl.events.IOErrorEvent;
|
||||
import openfl.events.IOErrorEvent;
|
||||
import openfl.events.IOErrorEvent;
|
||||
import openfl.media.Sound;
|
||||
import openfl.net.FileReference;
|
||||
import openfl.utils.ByteArray;
|
||||
|
||||
using StringTools;
|
||||
|
||||
@@ -372,16 +374,24 @@ class ChartingState extends MusicBeatState
|
||||
|
||||
var updatedSection:Bool = false;
|
||||
|
||||
function lengthBpmBullshit():Float
|
||||
{
|
||||
if (_song.notes[curSection].changeBPM)
|
||||
return _song.notes[curSection].lengthInSteps * (_song.notes[curSection].bpm / _song.bpm);
|
||||
else
|
||||
return _song.notes[curSection].lengthInSteps;
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
Conductor.songPosition = FlxG.sound.music.time;
|
||||
_song.song = typingShit.text;
|
||||
|
||||
strumLine.y = getYfromStrum(Conductor.songPosition % (Conductor.stepCrochet * _song.notes[curSection].lengthInSteps));
|
||||
strumLine.y = getYfromStrum(Conductor.songPosition % (Conductor.stepCrochet * lengthBpmBullshit()));
|
||||
|
||||
if (curBeat % 4 == 0)
|
||||
{
|
||||
if (curStep > (_song.notes[curSection].lengthInSteps) * (curSection + 1))
|
||||
if (curStep > 16 * (curSection + 1))
|
||||
{
|
||||
trace(curStep);
|
||||
trace((_song.notes[curSection].lengthInSteps) * (curSection + 1));
|
||||
@@ -396,6 +406,9 @@ class ChartingState extends MusicBeatState
|
||||
}
|
||||
}
|
||||
|
||||
FlxG.watch.addQuick('daBeat', curBeat);
|
||||
FlxG.watch.addQuick('daStep', curStep);
|
||||
|
||||
if (FlxG.mouse.justPressed)
|
||||
{
|
||||
if (FlxG.mouse.overlaps(curRenderedNotes))
|
||||
@@ -523,14 +536,14 @@ class ChartingState extends MusicBeatState
|
||||
vocals.pause();
|
||||
|
||||
var daNum:Int = 0;
|
||||
var daLength:Int = 0;
|
||||
var daLength:Float = 0;
|
||||
while (daNum <= sec)
|
||||
{
|
||||
daLength += _song.notes[daNum].lengthInSteps;
|
||||
daLength += lengthBpmBullshit();
|
||||
daNum++;
|
||||
}
|
||||
|
||||
FlxG.sound.music.time = (daLength - (_song.notes[sec].lengthInSteps)) * Conductor.stepCrochet;
|
||||
FlxG.sound.music.time = (daLength - lengthBpmBullshit()) * Conductor.stepCrochet;
|
||||
vocals.time = FlxG.sound.music.time;
|
||||
updateCurStep();
|
||||
}
|
||||
@@ -618,7 +631,7 @@ class ChartingState extends MusicBeatState
|
||||
note.setGraphicSize(GRID_SIZE, GRID_SIZE);
|
||||
note.updateHitbox();
|
||||
note.x = Math.floor(daNoteInfo * GRID_SIZE);
|
||||
note.y = getYfromStrum(daStrumTime) % gridBG.height;
|
||||
note.y = Math.floor(getYfromStrum(daStrumTime)) % gridBG.height;
|
||||
|
||||
curRenderedNotes.add(note);
|
||||
|
||||
@@ -689,7 +702,7 @@ class ChartingState extends MusicBeatState
|
||||
|
||||
private function addNote():Void
|
||||
{
|
||||
var noteStrum = Math.round(getStrumTime(dummyArrow.y) + (curSection * (Conductor.stepCrochet * 16)));
|
||||
var noteStrum = getStrumTime(dummyArrow.y) + (curSection * (Conductor.stepCrochet * 16));
|
||||
var noteData = Math.floor(FlxG.mouse.x / GRID_SIZE);
|
||||
var noteSus = 0;
|
||||
|
||||
@@ -697,7 +710,7 @@ class ChartingState extends MusicBeatState
|
||||
|
||||
curSelectedNote = _song.notes[curSection].sectionNotes[_song.notes[curSection].sectionNotes.length - 1];
|
||||
|
||||
trace(getStrumTime(dummyArrow.y) + (curSection * (Conductor.stepCrochet * 16)));
|
||||
trace(getStrumTime(dummyArrow.y) + (curSection * (Conductor.stepCrochet * lengthBpmBullshit())));
|
||||
trace(curSection);
|
||||
|
||||
updateGrid();
|
||||
@@ -758,10 +771,17 @@ class ChartingState extends MusicBeatState
|
||||
|
||||
function loadJson(song:String):Void
|
||||
{
|
||||
PlayState.SONG = Song.loadFromJson(song);
|
||||
PlayState.SONG = Song.loadFromJson(song.toLowerCase(), song.toLowerCase());
|
||||
FlxG.resetState();
|
||||
}
|
||||
|
||||
var mp3File:Sound;
|
||||
var waveForm:FlxSprite;
|
||||
|
||||
function drawWave():Void
|
||||
{
|
||||
}
|
||||
|
||||
private function saveLevel()
|
||||
{
|
||||
var json = {
|
||||
|
||||
@@ -108,7 +108,11 @@ class Controls extends FlxActionSet
|
||||
var _pause = new FlxActionDigital(Action.PAUSE);
|
||||
var _reset = new FlxActionDigital(Action.RESET);
|
||||
|
||||
#if (haxe >= "4.0.0")
|
||||
var byName:Map<String, FlxActionDigital> = [];
|
||||
#else
|
||||
var byName:Map<String, FlxActionDigital> = new Map<String, FlxActionDigital>();
|
||||
#end
|
||||
|
||||
public var gamepadsAdded:Array<Int> = [];
|
||||
public var keyboardScheme = KeyboardScheme.None;
|
||||
@@ -193,6 +197,7 @@ class Controls extends FlxActionSet
|
||||
inline function get_RESET()
|
||||
return _reset.check();
|
||||
|
||||
#if (haxe >= "4.0.0")
|
||||
public function new(name, scheme = None)
|
||||
{
|
||||
super(name);
|
||||
@@ -219,6 +224,36 @@ class Controls extends FlxActionSet
|
||||
|
||||
setKeyboardScheme(scheme, false);
|
||||
}
|
||||
#else
|
||||
public function new(name, scheme:KeyboardScheme = null)
|
||||
{
|
||||
super(name);
|
||||
|
||||
add(_up);
|
||||
add(_left);
|
||||
add(_right);
|
||||
add(_down);
|
||||
add(_upP);
|
||||
add(_leftP);
|
||||
add(_rightP);
|
||||
add(_downP);
|
||||
add(_upR);
|
||||
add(_leftR);
|
||||
add(_rightR);
|
||||
add(_downR);
|
||||
add(_accept);
|
||||
add(_back);
|
||||
add(_pause);
|
||||
add(_reset);
|
||||
|
||||
for (action in digitalActions)
|
||||
byName[action.name] = action;
|
||||
|
||||
if (scheme == null)
|
||||
scheme = None;
|
||||
setKeyboardScheme(scheme, false);
|
||||
}
|
||||
#end
|
||||
|
||||
override function update()
|
||||
{
|
||||
@@ -278,7 +313,7 @@ class Controls extends FlxActionSet
|
||||
* @param func
|
||||
* @return ->Void)
|
||||
*/
|
||||
function forEachBound(control:Control, func:(FlxActionDigital, FlxInputState) -> Void)
|
||||
function forEachBound(control:Control, func:FlxActionDigital->FlxInputState->Void)
|
||||
{
|
||||
switch (control)
|
||||
{
|
||||
@@ -332,6 +367,7 @@ class Controls extends FlxActionSet
|
||||
|
||||
public function copyFrom(controls:Controls, ?device:Device)
|
||||
{
|
||||
#if (haxe >= "4.0.0")
|
||||
for (name => action in controls.byName)
|
||||
{
|
||||
for (input in action.inputs)
|
||||
@@ -340,14 +376,31 @@ class Controls extends FlxActionSet
|
||||
byName[name].add(cast input);
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (name in controls.byName.keys())
|
||||
{
|
||||
var action = controls.byName[name];
|
||||
for (input in action.inputs)
|
||||
{
|
||||
if (device == null || isDevice(input, device))
|
||||
byName[name].add(cast input);
|
||||
}
|
||||
}
|
||||
#end
|
||||
|
||||
switch (device)
|
||||
{
|
||||
case null:
|
||||
// add all
|
||||
#if (haxe >= "4.0.0")
|
||||
for (gamepad in controls.gamepadsAdded)
|
||||
if (!gamepadsAdded.contains(gamepad))
|
||||
gamepadsAdded.push(gamepad);
|
||||
#else
|
||||
for (gamepad in controls.gamepadsAdded)
|
||||
if (gamepadsAdded.indexOf(gamepad) == -1)
|
||||
gamepadsAdded.push(gamepad);
|
||||
#end
|
||||
|
||||
mergeKeyboardScheme(controls.keyboardScheme);
|
||||
|
||||
@@ -383,7 +436,11 @@ class Controls extends FlxActionSet
|
||||
*/
|
||||
public function bindKeys(control:Control, keys:Array<FlxKey>)
|
||||
{
|
||||
#if (haxe >= "4.0.0")
|
||||
inline forEachBound(control, (action, state) -> addKeys(action, keys, state));
|
||||
#else
|
||||
forEachBound(control, function(action, state) addKeys(action, keys, state));
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -392,7 +449,11 @@ class Controls extends FlxActionSet
|
||||
*/
|
||||
public function unbindKeys(control:Control, keys:Array<FlxKey>)
|
||||
{
|
||||
#if (haxe >= "4.0.0")
|
||||
inline forEachBound(control, (action, _) -> removeKeys(action, keys));
|
||||
#else
|
||||
forEachBound(control, function(action, _) removeKeys(action, keys));
|
||||
#end
|
||||
}
|
||||
|
||||
inline static function addKeys(action:FlxActionDigital, keys:Array<FlxKey>, state:FlxInputState)
|
||||
@@ -418,6 +479,8 @@ class Controls extends FlxActionSet
|
||||
removeKeyboard();
|
||||
|
||||
keyboardScheme = scheme;
|
||||
|
||||
#if (haxe >= "4.0.0")
|
||||
switch (scheme)
|
||||
{
|
||||
case Solo:
|
||||
@@ -450,6 +513,40 @@ class Controls extends FlxActionSet
|
||||
case None: // nothing
|
||||
case Custom: // nothing
|
||||
}
|
||||
#else
|
||||
switch (scheme)
|
||||
{
|
||||
case Solo:
|
||||
bindKeys(Control.UP, [W, FlxKey.UP]);
|
||||
bindKeys(Control.DOWN, [S, FlxKey.DOWN]);
|
||||
bindKeys(Control.LEFT, [A, FlxKey.LEFT]);
|
||||
bindKeys(Control.RIGHT, [D, FlxKey.RIGHT]);
|
||||
bindKeys(Control.ACCEPT, [Z, SPACE, ENTER]);
|
||||
bindKeys(Control.BACK, [BACKSPACE, ESCAPE]);
|
||||
bindKeys(Control.PAUSE, [P, ENTER, ESCAPE]);
|
||||
bindKeys(Control.RESET, [R]);
|
||||
case Duo(true):
|
||||
bindKeys(Control.UP, [W]);
|
||||
bindKeys(Control.DOWN, [S]);
|
||||
bindKeys(Control.LEFT, [A]);
|
||||
bindKeys(Control.RIGHT, [D]);
|
||||
bindKeys(Control.ACCEPT, [G, Z]);
|
||||
bindKeys(Control.BACK, [H, X]);
|
||||
bindKeys(Control.PAUSE, [ONE]);
|
||||
bindKeys(Control.RESET, [R]);
|
||||
case Duo(false):
|
||||
bindKeys(Control.UP, [FlxKey.UP]);
|
||||
bindKeys(Control.DOWN, [FlxKey.DOWN]);
|
||||
bindKeys(Control.LEFT, [FlxKey.LEFT]);
|
||||
bindKeys(Control.RIGHT, [FlxKey.RIGHT]);
|
||||
bindKeys(Control.ACCEPT, [O]);
|
||||
bindKeys(Control.BACK, [P]);
|
||||
bindKeys(Control.PAUSE, [ENTER]);
|
||||
bindKeys(Control.RESET, [BACKSPACE]);
|
||||
case None: // nothing
|
||||
case Custom: // nothing
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
function removeKeyboard()
|
||||
@@ -469,15 +566,27 @@ class Controls extends FlxActionSet
|
||||
public function addGamepad(id:Int, ?buttonMap:Map<Control, Array<FlxGamepadInputID>>):Void
|
||||
{
|
||||
gamepadsAdded.push(id);
|
||||
|
||||
#if (haxe >= "4.0.0")
|
||||
for (control => buttons in buttonMap)
|
||||
bindButtons(control, id, buttons);
|
||||
inline bindButtons(control, id, buttons);
|
||||
#else
|
||||
for (control in buttonMap.keys())
|
||||
bindButtons(control, id, buttonMap[control]);
|
||||
#end
|
||||
}
|
||||
|
||||
inline function addGamepadLiteral(id:Int, ?buttonMap:Map<Control, Array<FlxGamepadInputID>>):Void
|
||||
{
|
||||
gamepadsAdded.push(id);
|
||||
|
||||
#if (haxe >= "4.0.0")
|
||||
for (control => buttons in buttonMap)
|
||||
inline bindButtons(control, id, buttons);
|
||||
#else
|
||||
for (control in buttonMap.keys())
|
||||
bindButtons(control, id, buttonMap[control]);
|
||||
#end
|
||||
}
|
||||
|
||||
public function removeGamepad(deviceID:Int = FlxInputDeviceID.ALL):Void
|
||||
@@ -498,6 +607,7 @@ class Controls extends FlxActionSet
|
||||
|
||||
public function addDefaultGamepad(id):Void
|
||||
{
|
||||
#if !switch
|
||||
addGamepadLiteral(id, [
|
||||
Control.ACCEPT => [A],
|
||||
Control.BACK => [B],
|
||||
@@ -508,6 +618,19 @@ class Controls extends FlxActionSet
|
||||
Control.PAUSE => [START],
|
||||
Control.RESET => [Y]
|
||||
]);
|
||||
#else
|
||||
addGamepadLiteral(id, [
|
||||
//Swap A and B for switch
|
||||
Control.ACCEPT => [B],
|
||||
Control.BACK => [A],
|
||||
Control.UP => [DPAD_UP, LEFT_STICK_DIGITAL_UP],
|
||||
Control.DOWN => [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN],
|
||||
Control.LEFT => [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT],
|
||||
Control.RIGHT => [DPAD_RIGHT, LEFT_STICK_DIGITAL_RIGHT],
|
||||
Control.PAUSE => [START],
|
||||
Control.RESET => [Y]
|
||||
]);
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -516,7 +639,11 @@ class Controls extends FlxActionSet
|
||||
*/
|
||||
public function bindButtons(control:Control, id, buttons)
|
||||
{
|
||||
#if (haxe >= "4.0.0")
|
||||
inline forEachBound(control, (action, state) -> addButtons(action, buttons, state, id));
|
||||
#else
|
||||
forEachBound(control, function(action, state) addButtons(action, buttons, state, id));
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -525,7 +652,11 @@ class Controls extends FlxActionSet
|
||||
*/
|
||||
public function unbindButtons(control:Control, gamepadID:Int, buttons)
|
||||
{
|
||||
#if (haxe >= "4.0.0")
|
||||
inline forEachBound(control, (action, _) -> removeButtons(action, gamepadID, buttons));
|
||||
#else
|
||||
forEachBound(control, function(action, _) removeButtons(action, gamepadID, buttons));
|
||||
#end
|
||||
}
|
||||
|
||||
inline static function addButtons(action:FlxActionDigital, buttons:Array<FlxGamepadInputID>, state, id)
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package;
|
||||
|
||||
import flash.text.TextField;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.addons.display.FlxGridOverlay;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.util.FlxColor;
|
||||
import lime.utils.Assets;
|
||||
|
||||
class FreeplayState extends MusicBeatState
|
||||
{
|
||||
@@ -12,15 +16,33 @@ class FreeplayState extends MusicBeatState
|
||||
|
||||
var selector:FlxText;
|
||||
var curSelected:Int = 0;
|
||||
var curDifficulty:Int = 1;
|
||||
|
||||
var scoreText:FlxText;
|
||||
var diffText:FlxText;
|
||||
var lerpScore:Int = 0;
|
||||
var intendedScore:Int = 0;
|
||||
|
||||
private var grpSongs:FlxTypedGroup<Alphabet>;
|
||||
private var curPlaying:Bool = false;
|
||||
|
||||
override function create()
|
||||
{
|
||||
if (!FlxG.sound.music.playing)
|
||||
FlxG.sound.playMusic('assets/music/freakyMenu' + TitleState.soundExt);
|
||||
/*
|
||||
if (FlxG.sound.music != null)
|
||||
{
|
||||
if (!FlxG.sound.music.playing)
|
||||
FlxG.sound.playMusic('assets/music/freakyMenu' + TitleState.soundExt);
|
||||
}
|
||||
*/
|
||||
|
||||
if (StoryMenuState.weekUnlocked[1])
|
||||
var isDebug:Bool = false;
|
||||
|
||||
#if debug
|
||||
isDebug = true;
|
||||
#end
|
||||
|
||||
if (StoryMenuState.weekUnlocked[1] || isDebug)
|
||||
{
|
||||
songs.push('Spookeez');
|
||||
songs.push('South');
|
||||
@@ -47,7 +69,23 @@ class FreeplayState extends MusicBeatState
|
||||
// songText.screenCenter(X);
|
||||
}
|
||||
|
||||
scoreText = new FlxText(FlxG.width * 0.7, 5, 0, "", 32);
|
||||
// scoreText.autoSize = false;
|
||||
scoreText.setFormat("assets/fonts/vcr.ttf", 32, FlxColor.WHITE, RIGHT);
|
||||
// scoreText.alignment = RIGHT;
|
||||
|
||||
var scoreBG:FlxSprite = new FlxSprite(scoreText.x - 6, 0).makeGraphic(Std.int(FlxG.width * 0.35), 66, 0xFF000000);
|
||||
scoreBG.alpha = 0.6;
|
||||
add(scoreBG);
|
||||
|
||||
diffText = new FlxText(scoreText.x, scoreText.y + 36, 0, "", 24);
|
||||
diffText.font = scoreText.font;
|
||||
add(diffText);
|
||||
|
||||
add(scoreText);
|
||||
|
||||
changeSelection();
|
||||
changeDiff();
|
||||
|
||||
// FlxG.sound.playMusic('assets/music/title' + TitleState.soundExt, 0);
|
||||
// FlxG.sound.music.fadeIn(2, 0, 0.8);
|
||||
@@ -59,12 +97,42 @@ class FreeplayState extends MusicBeatState
|
||||
|
||||
var swag:Alphabet = new Alphabet(1, 0, "swag");
|
||||
|
||||
// JUST DOIN THIS SHIT FOR TESTING!!!
|
||||
/*
|
||||
var md:String = Markdown.markdownToHtml(Assets.getText('CHANGELOG.md'));
|
||||
|
||||
var texFel:TextField = new TextField();
|
||||
texFel.width = FlxG.width;
|
||||
texFel.height = FlxG.height;
|
||||
// texFel.
|
||||
texFel.htmlText = md;
|
||||
|
||||
FlxG.stage.addChild(texFel);
|
||||
|
||||
// scoreText.textField.htmlText = md;
|
||||
|
||||
trace(md);
|
||||
*/
|
||||
|
||||
super.create();
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
if (FlxG.sound.music.volume < 0.7)
|
||||
{
|
||||
FlxG.sound.music.volume += 0.5 * FlxG.elapsed;
|
||||
}
|
||||
|
||||
lerpScore = Math.floor(FlxMath.lerp(lerpScore, intendedScore, 0.4));
|
||||
|
||||
if (Math.abs(lerpScore - intendedScore) <= 10)
|
||||
lerpScore = intendedScore;
|
||||
|
||||
scoreText.text = "PERSONAL BEST:" + lerpScore;
|
||||
|
||||
var upP = controls.UP_P;
|
||||
var downP = controls.DOWN_P;
|
||||
var accepted = controls.ACCEPT;
|
||||
@@ -78,6 +146,11 @@ class FreeplayState extends MusicBeatState
|
||||
changeSelection(1);
|
||||
}
|
||||
|
||||
if (controls.LEFT_P)
|
||||
changeDiff(-1);
|
||||
if (controls.RIGHT_P)
|
||||
changeDiff(1);
|
||||
|
||||
if (controls.BACK)
|
||||
{
|
||||
FlxG.switchState(new MainMenuState());
|
||||
@@ -85,15 +158,46 @@ class FreeplayState extends MusicBeatState
|
||||
|
||||
if (accepted)
|
||||
{
|
||||
PlayState.SONG = Song.loadFromJson(songs[curSelected].toLowerCase(), songs[curSelected].toLowerCase());
|
||||
var poop:String = Highscore.formatSong(songs[curSelected].toLowerCase(), curDifficulty);
|
||||
|
||||
trace(poop);
|
||||
|
||||
PlayState.SONG = Song.loadFromJson(poop, songs[curSelected].toLowerCase());
|
||||
PlayState.isStoryMode = false;
|
||||
PlayState.storyDifficulty = curDifficulty;
|
||||
FlxG.switchState(new PlayState());
|
||||
FlxG.sound.music.stop();
|
||||
if (FlxG.sound.music != null)
|
||||
FlxG.sound.music.stop();
|
||||
}
|
||||
}
|
||||
|
||||
function changeDiff(change:Int = 0)
|
||||
{
|
||||
curDifficulty += change;
|
||||
|
||||
if (curDifficulty < 0)
|
||||
curDifficulty = 2;
|
||||
if (curDifficulty > 2)
|
||||
curDifficulty = 0;
|
||||
|
||||
intendedScore = Highscore.getScore(songs[curSelected], curDifficulty);
|
||||
|
||||
switch (curDifficulty)
|
||||
{
|
||||
case 0:
|
||||
diffText.text = "EASY";
|
||||
case 1:
|
||||
diffText.text = 'NORMAL';
|
||||
case 2:
|
||||
diffText.text = "HARD";
|
||||
}
|
||||
}
|
||||
|
||||
function changeSelection(change:Int = 0)
|
||||
{
|
||||
// NGio.logEvent('Fresh');
|
||||
FlxG.sound.play('assets/sounds/scrollMenu' + TitleState.soundExt, 0.4);
|
||||
|
||||
curSelected += change;
|
||||
|
||||
if (curSelected < 0)
|
||||
@@ -103,6 +207,11 @@ class FreeplayState extends MusicBeatState
|
||||
|
||||
// selector.y = (70 * curSelected) + 30;
|
||||
|
||||
intendedScore = Highscore.getScore(songs[curSelected], curDifficulty);
|
||||
// lerpScore = 0;
|
||||
|
||||
FlxG.sound.playMusic('assets/music/' + songs[curSelected] + "_Inst" + TitleState.soundExt, 0);
|
||||
|
||||
var bullShit:Int = 0;
|
||||
|
||||
for (item in grpSongs.members)
|
||||
|
||||
@@ -12,6 +12,8 @@ class GameOverSubstate extends MusicBeatSubstate
|
||||
var bf:Boyfriend;
|
||||
var camFollow:FlxObject;
|
||||
|
||||
// var
|
||||
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
super();
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package;
|
||||
|
||||
import flixel.FlxG;
|
||||
|
||||
class Highscore
|
||||
{
|
||||
public static var songScores:Map<String, Int> = new Map();
|
||||
|
||||
public static function saveScore(song:String, score:Int = 0, ?diff:Int = 0):Void
|
||||
{
|
||||
var daSong:String = formatSong(song, diff);
|
||||
|
||||
NGio.postScore(score, song);
|
||||
|
||||
if (songScores.exists(daSong))
|
||||
{
|
||||
if (songScores.get(daSong) < score)
|
||||
setScore(daSong, score);
|
||||
}
|
||||
else
|
||||
setScore(daSong, score);
|
||||
}
|
||||
|
||||
public static function saveWeekScore(week:Int = 1, score:Int = 0, ?diff:Int = 0):Void
|
||||
{
|
||||
NGio.postScore(score, "Week " + week);
|
||||
|
||||
var daWeek:String = formatSong('week' + week, diff);
|
||||
|
||||
if (songScores.exists(daWeek))
|
||||
{
|
||||
if (songScores.get(daWeek) < score)
|
||||
setScore(daWeek, score);
|
||||
}
|
||||
else
|
||||
setScore(daWeek, score);
|
||||
}
|
||||
|
||||
/**
|
||||
* YOU SHOULD FORMAT SONG WITH formatSong() BEFORE TOSSING IN SONG VARIABLE
|
||||
*/
|
||||
static function setScore(song:String, score:Int):Void
|
||||
{
|
||||
// Reminder that I don't need to format this song, it should come formatted!
|
||||
songScores.set(song, score);
|
||||
FlxG.save.data.songScores = songScores;
|
||||
FlxG.save.flush();
|
||||
}
|
||||
|
||||
public static function formatSong(song:String, diff:Int):String
|
||||
{
|
||||
var daSong:String = song;
|
||||
|
||||
if (diff == 0)
|
||||
daSong += '-easy';
|
||||
else if (diff == 2)
|
||||
daSong += '-hard';
|
||||
|
||||
return daSong;
|
||||
}
|
||||
|
||||
public static function getScore(song:String, diff:Int):Int
|
||||
{
|
||||
if (!songScores.exists(formatSong(song, diff)))
|
||||
setScore(formatSong(song, diff), 0);
|
||||
|
||||
return songScores.get(formatSong(song, diff));
|
||||
}
|
||||
|
||||
public static function getWeekScore(week:Int, diff:Int):Int
|
||||
{
|
||||
if (!songScores.exists(formatSong('week' + week, diff)))
|
||||
setScore(formatSong('week' + week, diff), 0);
|
||||
|
||||
return songScores.get(formatSong('week' + week, diff));
|
||||
}
|
||||
|
||||
public static function load():Void
|
||||
{
|
||||
if (FlxG.save.data.songScores != null)
|
||||
{
|
||||
songScores = FlxG.save.data.songScores;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,11 @@ import flixel.FlxSprite;
|
||||
import flixel.effects.FlxFlicker;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.tweens.FlxEase;
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.util.FlxColor;
|
||||
import lime.app.Application;
|
||||
|
||||
class MainMenuState extends MusicBeatState
|
||||
{
|
||||
@@ -36,7 +39,7 @@ class MainMenuState extends MusicBeatState
|
||||
camFollow = new FlxObject(0, 0, 1, 1);
|
||||
add(camFollow);
|
||||
|
||||
magenta = new FlxSprite(-80).loadGraphic(AssetPaths.menuBGMagenta__png);
|
||||
magenta = new FlxSprite(-80).loadGraphic(AssetPaths.menuDesat__png);
|
||||
magenta.scrollFactor.x = 0;
|
||||
magenta.scrollFactor.y = 0.18;
|
||||
magenta.setGraphicSize(Std.int(magenta.width * 1.1));
|
||||
@@ -44,6 +47,7 @@ class MainMenuState extends MusicBeatState
|
||||
magenta.screenCenter();
|
||||
magenta.visible = false;
|
||||
magenta.antialiasing = true;
|
||||
magenta.color = 0xFFfd719b;
|
||||
add(magenta);
|
||||
// magenta.scrollFactor.set();
|
||||
|
||||
@@ -68,75 +72,88 @@ class MainMenuState extends MusicBeatState
|
||||
|
||||
FlxG.camera.follow(camFollow, null, 0.06);
|
||||
|
||||
var versionShit:FlxText = new FlxText(5, FlxG.height - 18, 0, "v" + Application.current.meta.get('version'));
|
||||
versionShit.scrollFactor.set();
|
||||
versionShit.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
|
||||
add(versionShit);
|
||||
|
||||
changeItem();
|
||||
|
||||
super.create();
|
||||
}
|
||||
|
||||
var selectedSomethin:Bool = false;
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (controls.UP_P)
|
||||
if (!selectedSomethin)
|
||||
{
|
||||
FlxG.sound.play('assets/sounds/scrollMenu' + TitleState.soundExt);
|
||||
changeItem(-1);
|
||||
}
|
||||
if (controls.UP_P)
|
||||
{
|
||||
FlxG.sound.play('assets/sounds/scrollMenu' + TitleState.soundExt);
|
||||
changeItem(-1);
|
||||
}
|
||||
|
||||
if (controls.DOWN_P)
|
||||
{
|
||||
FlxG.sound.play('assets/sounds/scrollMenu' + TitleState.soundExt);
|
||||
changeItem(1);
|
||||
}
|
||||
if (controls.DOWN_P)
|
||||
{
|
||||
FlxG.sound.play('assets/sounds/scrollMenu' + TitleState.soundExt);
|
||||
changeItem(1);
|
||||
}
|
||||
|
||||
if (controls.BACK)
|
||||
{
|
||||
FlxG.switchState(new TitleState());
|
||||
if (controls.BACK)
|
||||
{
|
||||
FlxG.switchState(new TitleState());
|
||||
}
|
||||
|
||||
if (controls.ACCEPT)
|
||||
{
|
||||
if (optionShit[curSelected] == 'donate')
|
||||
{
|
||||
FlxG.openURL('https://ninja-muffin24.itch.io/funkin');
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedSomethin = true;
|
||||
FlxG.sound.play('assets/sounds/confirmMenu' + TitleState.soundExt);
|
||||
|
||||
FlxFlicker.flicker(magenta, 1.1, 0.15, false);
|
||||
|
||||
menuItems.forEach(function(spr:FlxSprite)
|
||||
{
|
||||
if (curSelected != spr.ID)
|
||||
{
|
||||
FlxTween.tween(spr, {alpha: 0}, 0.4, {
|
||||
ease: FlxEase.quadOut,
|
||||
onComplete: function(twn:FlxTween)
|
||||
{
|
||||
spr.kill();
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
FlxFlicker.flicker(spr, 1, 0.06, false, false, function(flick:FlxFlicker)
|
||||
{
|
||||
var daChoice:String = optionShit[curSelected];
|
||||
|
||||
switch (daChoice)
|
||||
{
|
||||
case 'story mode':
|
||||
FlxG.switchState(new StoryMenuState());
|
||||
case 'freeplay':
|
||||
FlxG.switchState(new FreeplayState());
|
||||
case 'options':
|
||||
FlxG.switchState(new OptionsMenu());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
|
||||
if (controls.ACCEPT)
|
||||
{
|
||||
if (optionShit[curSelected] == 'donate')
|
||||
{
|
||||
FlxG.openURL('https://ninja-muffin24.itch.io/funkin');
|
||||
}
|
||||
else
|
||||
{
|
||||
FlxG.sound.play('assets/sounds/confirmMenu' + TitleState.soundExt);
|
||||
|
||||
FlxFlicker.flicker(magenta, 1.1, 0.15, false);
|
||||
|
||||
menuItems.forEach(function(spr:FlxSprite)
|
||||
{
|
||||
if (curSelected != spr.ID)
|
||||
{
|
||||
FlxTween.tween(spr, {alpha: 0}, 0.4, {
|
||||
ease: FlxEase.quadOut,
|
||||
onComplete: function(twn:FlxTween)
|
||||
{
|
||||
spr.kill();
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
FlxFlicker.flicker(spr, 1, 0.06, false, false, function(flick:FlxFlicker)
|
||||
{
|
||||
var daChoice:String = optionShit[curSelected];
|
||||
|
||||
switch (daChoice)
|
||||
{
|
||||
case 'story mode':
|
||||
FlxG.switchState(new StoryMenuState());
|
||||
case 'freeplay':
|
||||
FlxG.switchState(new FreeplayState());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
menuItems.forEach(function(spr:FlxSprite)
|
||||
{
|
||||
spr.screenCenter(X);
|
||||
|
||||
@@ -10,7 +10,7 @@ class MenuItem extends FlxSpriteGroup
|
||||
public var targetY:Float = 0;
|
||||
public var week:FlxSprite;
|
||||
|
||||
public function new(x:Float, y:Float, weekNum:Int = 0, unlocked:Bool = false)
|
||||
public function new(x:Float, y:Float, weekNum:Int = 0)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
@@ -18,18 +18,15 @@ class MenuItem extends FlxSpriteGroup
|
||||
|
||||
week = new FlxSprite();
|
||||
week.frames = tex;
|
||||
week.animation.addByPrefix('week0', "WEEK1 select", 24);
|
||||
week.animation.addByPrefix('week1', "week2 select", 24);
|
||||
// TUTORIAL IS WEEK 0
|
||||
week.animation.addByPrefix('week0', 'tutorial selected', 24);
|
||||
week.animation.addByPrefix('week1', "WEEK1 select", 24);
|
||||
week.animation.addByPrefix('week2', "week2 select", 24);
|
||||
add(week);
|
||||
|
||||
week.animation.play('week' + weekNum);
|
||||
week.animation.pause();
|
||||
week.updateHitbox();
|
||||
|
||||
if (!unlocked)
|
||||
{
|
||||
week.alpha = 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
|
||||
@@ -34,6 +34,7 @@ class MusicBeatState extends FlxUIState
|
||||
everyStep();
|
||||
|
||||
updateCurStep();
|
||||
// Needs to be ROUNED, rather than ceil or floor
|
||||
curBeat = Math.round(curStep / 4);
|
||||
|
||||
super.update(elapsed);
|
||||
@@ -64,6 +65,13 @@ class MusicBeatState extends FlxUIState
|
||||
totalSteps += 1;
|
||||
lastStep += Conductor.stepCrochet;
|
||||
|
||||
// If the song is at least 3 steps behind
|
||||
if (Conductor.songPosition > lastStep + (Conductor.stepCrochet * 3))
|
||||
{
|
||||
lastStep = Conductor.songPosition;
|
||||
totalSteps = Math.ceil(lastStep / Conductor.stepCrochet);
|
||||
}
|
||||
|
||||
if (totalSteps % 4 == 0)
|
||||
beatHit();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSubState;
|
||||
|
||||
class MusicBeatSubstate extends FlxSubState
|
||||
|
||||
@@ -109,6 +109,24 @@ class NGio
|
||||
// more info on scores --- http://www.newgrounds.io/help/components/#scoreboard-getscores
|
||||
}
|
||||
|
||||
inline static public function postScore(score:Int = 0, song:String)
|
||||
{
|
||||
if (isLoggedIn)
|
||||
{
|
||||
for (id in NG.core.scoreBoards.keys())
|
||||
{
|
||||
var board = NG.core.scoreBoards.get(id);
|
||||
|
||||
if (song == board.name)
|
||||
{
|
||||
board.postScore(score, "Uhh meow?");
|
||||
}
|
||||
|
||||
// trace('loaded scoreboard id:$id, name:${board.name}');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onNGScoresFetch():Void
|
||||
{
|
||||
scoreboardsLoaded = true;
|
||||
@@ -128,6 +146,15 @@ class NGio
|
||||
// NGio.scoreboardArray = NG.core.scoreBoards.get(8004).scores;
|
||||
}
|
||||
|
||||
inline static public function logEvent(event:String)
|
||||
{
|
||||
if (isLoggedIn)
|
||||
{
|
||||
NG.core.calls.event.logEvent(event);
|
||||
trace('should have logged: ' + event);
|
||||
}
|
||||
}
|
||||
|
||||
inline static public function unlockMedal(id:Int)
|
||||
{
|
||||
if (isLoggedIn)
|
||||
|
||||
@@ -37,6 +37,8 @@ class Note extends FlxSprite
|
||||
isSustainNote = sustainNote;
|
||||
|
||||
x += 50;
|
||||
// MAKE SURE ITS DEFINITELY OFF SCREEN?
|
||||
y -= 2000;
|
||||
this.strumTime = strumTime;
|
||||
|
||||
this.noteData = noteData;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.util.FlxColor;
|
||||
|
||||
class OptionsMenu extends MusicBeatState
|
||||
{
|
||||
override function create()
|
||||
{
|
||||
var menuBG:FlxSprite = new FlxSprite().loadGraphic(AssetPaths.menuDesat__png);
|
||||
menuBG.color = 0xFFea71fd;
|
||||
menuBG.setGraphicSize(Std.int(menuBG.width * 1.1));
|
||||
menuBG.updateHitbox();
|
||||
menuBG.screenCenter();
|
||||
menuBG.antialiasing = true;
|
||||
add(menuBG);
|
||||
|
||||
super.create();
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (controls.BACK)
|
||||
FlxG.switchState(new MainMenuState());
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package;
|
||||
|
||||
class OptionsSubState extends MusicBeatSubstate
|
||||
{
|
||||
var textMenuItems:Array<String> = ['Master Volume', 'Sound Volume'];
|
||||
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -4,38 +4,124 @@ import Controls.Control;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxSubState;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.input.keyboard.FlxKey;
|
||||
import flixel.system.FlxSound;
|
||||
import flixel.util.FlxColor;
|
||||
|
||||
class PauseSubState extends FlxSubState
|
||||
class PauseSubState extends MusicBeatSubstate
|
||||
{
|
||||
var grpMenuShit:FlxTypedGroup<Alphabet>;
|
||||
|
||||
var menuItems:Array<String> = ['Resume', 'Restart Song', 'Exit to menu'];
|
||||
var curSelected:Int = 0;
|
||||
|
||||
var pauseMusic:FlxSound;
|
||||
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
super();
|
||||
|
||||
pauseMusic = new FlxSound().loadEmbedded('assets/music/breakfast' + TitleState.soundExt, true, true);
|
||||
pauseMusic.volume = 0;
|
||||
pauseMusic.play(false, FlxG.random.int(0, Std.int(pauseMusic.length / 2)));
|
||||
|
||||
FlxG.sound.list.add(pauseMusic);
|
||||
|
||||
var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
|
||||
bg.alpha = 0.6;
|
||||
bg.scrollFactor.set();
|
||||
add(bg);
|
||||
|
||||
var bf:Boyfriend = new Boyfriend(x, y);
|
||||
bf.scrollFactor.set();
|
||||
// add(bf);
|
||||
grpMenuShit = new FlxTypedGroup<Alphabet>();
|
||||
add(grpMenuShit);
|
||||
|
||||
bf.playAnim('firstDeath');
|
||||
for (i in 0...menuItems.length)
|
||||
{
|
||||
var songText:Alphabet = new Alphabet(0, (70 * i) + 30, menuItems[i], true, false);
|
||||
songText.isMenuItem = true;
|
||||
songText.targetY = i;
|
||||
grpMenuShit.add(songText);
|
||||
}
|
||||
|
||||
bg.cameras = [FlxG.cameras.list[1]];
|
||||
changeSelection();
|
||||
|
||||
cameras = [FlxG.cameras.list[1]];
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (pauseMusic.volume < 0.5)
|
||||
pauseMusic.volume += 0.01 * elapsed;
|
||||
|
||||
super.update(elapsed);
|
||||
|
||||
var upP = controls.UP_P;
|
||||
var downP = controls.DOWN_P;
|
||||
var accepted = controls.ACCEPT;
|
||||
|
||||
if (upP)
|
||||
{
|
||||
changeSelection(-1);
|
||||
}
|
||||
if (downP)
|
||||
{
|
||||
changeSelection(1);
|
||||
}
|
||||
|
||||
if (accepted)
|
||||
{
|
||||
var daSelected:String = menuItems[curSelected];
|
||||
|
||||
switch (daSelected)
|
||||
{
|
||||
case "Resume":
|
||||
close();
|
||||
case "Restart Song":
|
||||
FlxG.resetState();
|
||||
case "Exit to menu":
|
||||
FlxG.switchState(new MainMenuState());
|
||||
}
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.J)
|
||||
{
|
||||
PlayerSettings.player1.controls.replaceBinding(Control.LEFT, Keys, FlxKey.J, null);
|
||||
// for reference later!
|
||||
// PlayerSettings.player1.controls.replaceBinding(Control.LEFT, Keys, FlxKey.J, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.ENTER)
|
||||
close();
|
||||
override function destroy()
|
||||
{
|
||||
pauseMusic.destroy();
|
||||
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
function changeSelection(change:Int = 0):Void
|
||||
{
|
||||
curSelected += change;
|
||||
|
||||
if (curSelected < 0)
|
||||
curSelected = menuItems.length - 1;
|
||||
if (curSelected >= menuItems.length)
|
||||
curSelected = 0;
|
||||
|
||||
var bullShit:Int = 0;
|
||||
|
||||
for (item in grpMenuShit.members)
|
||||
{
|
||||
item.targetY = bullShit - curSelected;
|
||||
bullShit++;
|
||||
|
||||
item.alpha = 0.6;
|
||||
// item.setGraphicSize(Std.int(item.width * 0.8));
|
||||
|
||||
if (item.targetY == 0)
|
||||
{
|
||||
item.alpha = 1;
|
||||
// item.setGraphicSize(Std.int(item.width));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ class PlayState extends MusicBeatState
|
||||
public static var curLevel:String = 'Tutorial';
|
||||
public static var SONG:SwagSong;
|
||||
public static var isStoryMode:Bool = false;
|
||||
public static var storyWeek:Int = 0;
|
||||
public static var storyPlaylist:Array<String> = [];
|
||||
public static var storyDifficulty:Int = 1;
|
||||
|
||||
@@ -78,8 +79,13 @@ class PlayState extends MusicBeatState
|
||||
var dialogue:Array<String> = ['blah blah blah', 'coolswag'];
|
||||
|
||||
var halloweenBG:FlxSprite;
|
||||
var isHalloween:Bool = false;
|
||||
|
||||
var talking:Bool = true;
|
||||
var songScore:Int = 0;
|
||||
var scoreTxt:FlxText;
|
||||
|
||||
public static var campaignScore:Int = 0;
|
||||
|
||||
override public function create()
|
||||
{
|
||||
@@ -135,6 +141,8 @@ class PlayState extends MusicBeatState
|
||||
halloweenBG.animation.play('idle');
|
||||
halloweenBG.antialiasing = true;
|
||||
add(halloweenBG);
|
||||
|
||||
isHalloween = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -245,6 +253,11 @@ class PlayState extends MusicBeatState
|
||||
// healthBar
|
||||
add(healthBar);
|
||||
|
||||
scoreTxt = new FlxText(healthBarBG.x + healthBarBG.width - 190, healthBarBG.y + 30, 0, "", 20);
|
||||
scoreTxt.setFormat("assets/fonts/vcr.ttf", 16, FlxColor.WHITE, RIGHT);
|
||||
scoreTxt.scrollFactor.set();
|
||||
add(scoreTxt);
|
||||
|
||||
healthHeads = new FlxSprite();
|
||||
var headTex = FlxAtlasFrames.fromSparrow(AssetPaths.healthHeads__png, AssetPaths.healthHeads__xml);
|
||||
healthHeads.frames = headTex;
|
||||
@@ -270,6 +283,7 @@ class PlayState extends MusicBeatState
|
||||
healthBar.cameras = [camHUD];
|
||||
healthBarBG.cameras = [camHUD];
|
||||
healthHeads.cameras = [camHUD];
|
||||
scoreTxt.cameras = [camHUD];
|
||||
doof.cameras = [camHUD];
|
||||
|
||||
// if (SONG.song == 'South')
|
||||
@@ -456,7 +470,7 @@ class PlayState extends MusicBeatState
|
||||
daBeats += 1;
|
||||
}
|
||||
|
||||
trace(unspawnNotes.length);
|
||||
// trace(unspawnNotes.length);
|
||||
// playerCounter += 1;
|
||||
|
||||
unspawnNotes.sort(sortByShit);
|
||||
@@ -558,7 +572,7 @@ class PlayState extends MusicBeatState
|
||||
{
|
||||
if (FlxG.sound.music != null)
|
||||
{
|
||||
vocals.time = FlxG.sound.music.time;
|
||||
vocals.time = Conductor.songPosition;
|
||||
|
||||
FlxG.sound.music.play();
|
||||
vocals.play();
|
||||
@@ -574,15 +588,15 @@ class PlayState extends MusicBeatState
|
||||
|
||||
private var paused:Bool = false;
|
||||
var startedCountdown:Bool = false;
|
||||
var canPause:Bool = true;
|
||||
|
||||
override public function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
// trace("SONG POS: " + Conductor.songPosition);
|
||||
// FlxG.sound.music.pitch = 2;
|
||||
scoreTxt.text = "Score:" + songScore;
|
||||
|
||||
if (FlxG.keys.justPressed.ENTER && startedCountdown)
|
||||
if (FlxG.keys.justPressed.ENTER && startedCountdown && canPause)
|
||||
{
|
||||
persistentUpdate = false;
|
||||
persistentDraw = true;
|
||||
@@ -591,15 +605,16 @@ class PlayState extends MusicBeatState
|
||||
openSubState(new PauseSubState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y));
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.ESCAPE)
|
||||
if (FlxG.keys.justPressed.SEVEN)
|
||||
{
|
||||
// FlxG.switchState(new ChartingState());
|
||||
FlxG.switchState(new ChartingState());
|
||||
}
|
||||
|
||||
// FlxG.watch.addQuick('VOL', vocals.amplitudeLeft);
|
||||
// FlxG.watch.addQuick('VOLRight', vocals.amplitudeRight);
|
||||
|
||||
healthHeads.setGraphicSize(Std.int(FlxMath.lerp(100, healthHeads.width, 0.98)));
|
||||
healthHeads.setGraphicSize(Std.int(FlxMath.lerp(150, healthHeads.width, 0.50)));
|
||||
healthHeads.updateHitbox();
|
||||
healthHeads.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 100, 0) * 0.01)) - (healthHeads.width / 2);
|
||||
|
||||
if (health > 2)
|
||||
@@ -612,8 +627,11 @@ class PlayState extends MusicBeatState
|
||||
|
||||
/* if (FlxG.keys.justPressed.NINE)
|
||||
FlxG.switchState(new Charting()); */
|
||||
// if (FlxG.keys.justPressed.EIGHT)
|
||||
// FlxG.switchState(new AnimationDebug(SONG.player2));
|
||||
|
||||
#if debug
|
||||
if (FlxG.keys.justPressed.EIGHT)
|
||||
FlxG.switchState(new AnimationDebug(SONG.player1));
|
||||
#end
|
||||
|
||||
if (startingSong)
|
||||
{
|
||||
@@ -677,7 +695,8 @@ class PlayState extends MusicBeatState
|
||||
|
||||
if (camZooming)
|
||||
{
|
||||
FlxG.camera.zoom = FlxMath.lerp(1.05, FlxG.camera.zoom, 0.96);
|
||||
FlxG.camera.zoom = FlxMath.lerp(1.05, FlxG.camera.zoom, 0.95);
|
||||
camHUD.zoom = FlxMath.lerp(1, camHUD.zoom, 0.95);
|
||||
}
|
||||
|
||||
FlxG.watch.addQuick("beatShit", totalBeats);
|
||||
@@ -759,6 +778,9 @@ class PlayState extends MusicBeatState
|
||||
|
||||
if (!daNote.mustPress && daNote.wasGoodHit)
|
||||
{
|
||||
if (SONG.song != 'Tutorial')
|
||||
camZooming = true;
|
||||
|
||||
switch (Math.abs(daNote.noteData))
|
||||
{
|
||||
case 2:
|
||||
@@ -771,6 +793,8 @@ class PlayState extends MusicBeatState
|
||||
dad.playAnim('singLEFT', true);
|
||||
}
|
||||
|
||||
dad.holdTimer = 0;
|
||||
|
||||
if (SONG.needsVoices)
|
||||
vocals.volume = 1;
|
||||
|
||||
@@ -780,6 +804,7 @@ class PlayState extends MusicBeatState
|
||||
}
|
||||
|
||||
daNote.y = (strumLine.y - (Conductor.songPosition - daNote.strumTime) * (0.45 * PlayState.SONG.speed));
|
||||
|
||||
// WIP interpolation shit? Need to fix the pause issue
|
||||
// daNote.y = (strumLine.y - (songTime - daNote.strumTime) * (0.45 * PlayState.SONG.speed));
|
||||
|
||||
@@ -806,10 +831,14 @@ class PlayState extends MusicBeatState
|
||||
|
||||
function endSong():Void
|
||||
{
|
||||
trace('SONG DONE' + isStoryMode);
|
||||
canPause = false;
|
||||
|
||||
Highscore.saveScore(SONG.song, songScore, storyDifficulty);
|
||||
|
||||
if (isStoryMode)
|
||||
{
|
||||
campaignScore += songScore;
|
||||
|
||||
storyPlaylist.remove(storyPlaylist[0]);
|
||||
|
||||
if (storyPlaylist.length <= 0)
|
||||
@@ -818,7 +847,13 @@ class PlayState extends MusicBeatState
|
||||
|
||||
FlxG.switchState(new StoryMenuState());
|
||||
|
||||
StoryMenuState.weekUnlocked[1] = true;
|
||||
StoryMenuState.weekUnlocked[2] = true;
|
||||
|
||||
NGio.unlockMedal(60961);
|
||||
Highscore.saveWeekScore(storyWeek, campaignScore, storyDifficulty);
|
||||
|
||||
FlxG.save.data.weekUnlocked = StoryMenuState.weekUnlocked;
|
||||
FlxG.save.flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -828,7 +863,10 @@ class PlayState extends MusicBeatState
|
||||
difficulty = '-easy';
|
||||
|
||||
if (storyDifficulty == 2)
|
||||
difficulty == '-hard';
|
||||
difficulty = '-hard';
|
||||
|
||||
trace('LOADING NEXT SONG');
|
||||
trace(PlayState.storyPlaylist[0].toLowerCase() + difficulty);
|
||||
|
||||
PlayState.SONG = Song.loadFromJson(PlayState.storyPlaylist[0].toLowerCase() + difficulty, PlayState.storyPlaylist[0]);
|
||||
FlxG.switchState(new PlayState());
|
||||
@@ -856,22 +894,28 @@ class PlayState extends MusicBeatState
|
||||
//
|
||||
|
||||
var rating:FlxSprite = new FlxSprite();
|
||||
var score:Int = 350;
|
||||
|
||||
var daRating:String = "sick";
|
||||
|
||||
if (noteDiff > Conductor.safeZoneOffset * 0.9)
|
||||
{
|
||||
daRating = 'shit';
|
||||
score = 50;
|
||||
}
|
||||
else if (noteDiff > Conductor.safeZoneOffset * 0.75)
|
||||
{
|
||||
daRating = 'bad';
|
||||
score = 100;
|
||||
}
|
||||
else if (noteDiff > Conductor.safeZoneOffset * 0.2)
|
||||
{
|
||||
daRating = 'good';
|
||||
score = 200;
|
||||
}
|
||||
|
||||
songScore += score;
|
||||
|
||||
/* if (combo > 60)
|
||||
daRating = 'sick';
|
||||
else if (combo > 12)
|
||||
@@ -921,7 +965,9 @@ class PlayState extends MusicBeatState
|
||||
numScore.acceleration.y = FlxG.random.int(200, 300);
|
||||
numScore.velocity.y -= FlxG.random.int(140, 160);
|
||||
numScore.velocity.x = FlxG.random.float(-5, 5);
|
||||
add(numScore);
|
||||
|
||||
if (combo >= 10 || combo == 0)
|
||||
add(numScore);
|
||||
|
||||
FlxTween.tween(numScore, {alpha: 0}, 0.2, {
|
||||
onComplete: function(tween:FlxTween)
|
||||
@@ -980,6 +1026,8 @@ class PlayState extends MusicBeatState
|
||||
// FlxG.watch.addQuick('asdfa', upP);
|
||||
if ((upP || rightP || downP || leftP) && !boyfriend.stunned && generatedMusic)
|
||||
{
|
||||
boyfriend.holdTimer = 0;
|
||||
|
||||
var possibleNotes:Array<Note> = [];
|
||||
|
||||
notes.forEachAlive(function(daNote:Note)
|
||||
@@ -987,7 +1035,6 @@ class PlayState extends MusicBeatState
|
||||
if (daNote.canBeHit && daNote.mustPress && !daNote.tooLate)
|
||||
{
|
||||
possibleNotes.push(daNote);
|
||||
trace('NOTE-' + daNote.strumTime + ' ADDED');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1051,9 +1098,9 @@ class PlayState extends MusicBeatState
|
||||
});
|
||||
}
|
||||
|
||||
if (upR || leftR || rightR || downR)
|
||||
if (boyfriend.holdTimer > Conductor.stepCrochet * 4 * 0.001 && !up && !down && !right && !left)
|
||||
{
|
||||
if (boyfriend.animation.curAnim.name.startsWith('sing'))
|
||||
if (boyfriend.animation.curAnim.name.startsWith('sing') && !boyfriend.animation.curAnim.name.endsWith('miss'))
|
||||
{
|
||||
boyfriend.playAnim('idle');
|
||||
}
|
||||
@@ -1107,6 +1154,8 @@ class PlayState extends MusicBeatState
|
||||
}
|
||||
combo = 0;
|
||||
|
||||
songScore -= 10;
|
||||
|
||||
FlxG.sound.play('assets/sounds/missnote' + FlxG.random.int(1, 3) + TitleState.soundExt, FlxG.random.float(0.1, 0.2));
|
||||
// FlxG.sound.play('assets/sounds/missnote1' + TitleState.soundExt, 1, false);
|
||||
// FlxG.log.add('played imss note');
|
||||
@@ -1178,7 +1227,6 @@ class PlayState extends MusicBeatState
|
||||
|
||||
function noteCheck(keyP:Bool, note:Note):Void
|
||||
{
|
||||
trace(note.noteData + ' note check here ' + keyP);
|
||||
if (keyP)
|
||||
goodNoteHit(note);
|
||||
else
|
||||
@@ -1229,6 +1277,18 @@ class PlayState extends MusicBeatState
|
||||
}
|
||||
}
|
||||
|
||||
function lightningStrikeShit():Void
|
||||
{
|
||||
FlxG.sound.play('assets/sounds/thunder_' + FlxG.random.int(1, 2) + TitleState.soundExt);
|
||||
halloweenBG.animation.play('lightning');
|
||||
|
||||
lightningStrikeBeat = curBeat;
|
||||
lightningOffset = FlxG.random.int(8, 24);
|
||||
|
||||
boyfriend.playAnim('scared', true);
|
||||
gf.playAnim('scared', true);
|
||||
}
|
||||
|
||||
override function stepHit()
|
||||
{
|
||||
if (SONG.needsVoices)
|
||||
@@ -1250,6 +1310,9 @@ class PlayState extends MusicBeatState
|
||||
super.stepHit();
|
||||
}
|
||||
|
||||
var lightningStrikeBeat:Int = 0;
|
||||
var lightningOffset:Int = 8;
|
||||
|
||||
override function beatHit()
|
||||
{
|
||||
super.beatHit();
|
||||
@@ -1276,9 +1339,13 @@ class PlayState extends MusicBeatState
|
||||
// FlxG.log.add('change bpm' + SONG.notes[Std.int(curStep / 16)].changeBPM);
|
||||
|
||||
if (camZooming && FlxG.camera.zoom < 1.35 && totalBeats % 4 == 0)
|
||||
FlxG.camera.zoom += 0.025;
|
||||
{
|
||||
FlxG.camera.zoom += 0.015;
|
||||
camHUD.zoom += 0.03;
|
||||
}
|
||||
|
||||
healthHeads.setGraphicSize(Std.int(healthHeads.width + 20));
|
||||
healthHeads.setGraphicSize(Std.int(healthHeads.width + 30));
|
||||
healthHeads.updateHitbox();
|
||||
|
||||
if (totalBeats % gfSpeed == 0)
|
||||
{
|
||||
@@ -1297,5 +1364,10 @@ class PlayState extends MusicBeatState
|
||||
dad.playAnim('cheer', true);
|
||||
}
|
||||
}
|
||||
|
||||
if (isHalloween && FlxG.random.bool(10) && curBeat > lightningStrikeBeat + lightningOffset)
|
||||
{
|
||||
lightningStrikeShit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,12 +14,21 @@ class PlayerSettings
|
||||
static public var player1(default, null):PlayerSettings;
|
||||
static public var player2(default, null):PlayerSettings;
|
||||
|
||||
#if (haxe >= "4.0.0")
|
||||
static public final onAvatarAdd = new FlxTypedSignal<PlayerSettings->Void>();
|
||||
static public final onAvatarRemove = new FlxTypedSignal<PlayerSettings->Void>();
|
||||
#else
|
||||
static public var onAvatarAdd = new FlxTypedSignal<PlayerSettings->Void>();
|
||||
static public var onAvatarRemove = new FlxTypedSignal<PlayerSettings->Void>();
|
||||
#end
|
||||
|
||||
public var id(default, null):Int;
|
||||
|
||||
#if (haxe >= "4.0.0")
|
||||
public final controls:Controls;
|
||||
#else
|
||||
public var controls:Controls;
|
||||
#end
|
||||
|
||||
// public var avatar:Player;
|
||||
// public var camera(get, never):PlayCamera;
|
||||
|
||||
@@ -49,6 +49,7 @@ class Song
|
||||
|
||||
public static function loadFromJson(jsonInput:String, ?folder:String):SwagSong
|
||||
{
|
||||
|
||||
var rawJson = Assets.getText('assets/data/' + folder.toLowerCase() + '/' + jsonInput.toLowerCase() + '.json').trim();
|
||||
|
||||
while (!rawJson.endsWith("}"))
|
||||
|
||||
@@ -5,6 +5,7 @@ import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.group.FlxGroup;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.util.FlxTimer;
|
||||
@@ -16,12 +17,12 @@ class StoryMenuState extends MusicBeatState
|
||||
{
|
||||
var scoreText:FlxText;
|
||||
|
||||
var weekData:Array<Dynamic> = [['Tutorial', 'Bopeebo', 'Fresh', 'Dadbattle'], ['Spookeez', 'South']];
|
||||
var weekData:Array<Dynamic> = [['Tutorial'], ['Bopeebo', 'Fresh', 'Dadbattle'], ['Spookeez', 'South']];
|
||||
var curDifficulty:Int = 1;
|
||||
|
||||
public static var weekUnlocked:Array<Bool> = [true, false];
|
||||
public static var weekUnlocked:Array<Bool> = [true, true, false];
|
||||
|
||||
var weekCharacters:Array<Dynamic> = [['dad', 'bf', 'gf'], ['spooky', 'bf', 'gf']];
|
||||
var weekCharacters:Array<Dynamic> = [['dad', 'bf', 'gf'], ['dad', 'bf', 'gf'], ['spooky', 'bf', 'gf']];
|
||||
var curWeek:Int = 0;
|
||||
|
||||
var txtTracklist:FlxText;
|
||||
@@ -38,8 +39,11 @@ class StoryMenuState extends MusicBeatState
|
||||
|
||||
override function create()
|
||||
{
|
||||
if (!FlxG.sound.music.playing)
|
||||
FlxG.sound.playMusic('assets/music/freakyMenu' + TitleState.soundExt);
|
||||
if (FlxG.sound.music != null)
|
||||
{
|
||||
if (!FlxG.sound.music.playing)
|
||||
FlxG.sound.playMusic('assets/music/freakyMenu' + TitleState.soundExt);
|
||||
}
|
||||
|
||||
persistentUpdate = persistentDraw = true;
|
||||
|
||||
@@ -65,12 +69,7 @@ class StoryMenuState extends MusicBeatState
|
||||
|
||||
for (i in 0...weekData.length)
|
||||
{
|
||||
var unlocked:Bool = true;
|
||||
|
||||
if (i == 1)
|
||||
unlocked = false;
|
||||
|
||||
var weekThing:MenuItem = new MenuItem(0, yellowBG.y + yellowBG.height + 10, i, unlocked);
|
||||
var weekThing:MenuItem = new MenuItem(0, yellowBG.y + yellowBG.height + 10, i);
|
||||
weekThing.y += ((weekThing.height + 20) * i);
|
||||
weekThing.targetY = i;
|
||||
grpWeekText.add(weekThing);
|
||||
@@ -79,6 +78,7 @@ class StoryMenuState extends MusicBeatState
|
||||
weekThing.antialiasing = true;
|
||||
// weekThing.updateHitbox();
|
||||
|
||||
// Needs an offset thingie
|
||||
if (!weekUnlocked[i])
|
||||
{
|
||||
var lock:FlxSprite = new FlxSprite(weekThing.width + 10 + weekThing.x);
|
||||
@@ -117,7 +117,7 @@ class StoryMenuState extends MusicBeatState
|
||||
difficultySelectors = new FlxGroup();
|
||||
add(difficultySelectors);
|
||||
|
||||
leftArrow = new FlxSprite(grpWeekText.members[0].x + 370, grpWeekText.members[0].y + 10);
|
||||
leftArrow = new FlxSprite(grpWeekText.members[0].x + grpWeekText.members[0].width + 10, grpWeekText.members[0].y + 10);
|
||||
leftArrow.frames = ui_tex;
|
||||
leftArrow.animation.addByPrefix('idle', "arrow left");
|
||||
leftArrow.animation.addByPrefix('press', "arrow push left");
|
||||
@@ -150,7 +150,7 @@ class StoryMenuState extends MusicBeatState
|
||||
txtTracklist.color = 0xFFe55777;
|
||||
add(txtTracklist);
|
||||
// add(rankText);
|
||||
// add(scoreText);
|
||||
add(scoreText);
|
||||
|
||||
updateText();
|
||||
|
||||
@@ -160,7 +160,9 @@ class StoryMenuState extends MusicBeatState
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
// scoreText.setFormat('VCR OSD Mono', 32);
|
||||
// scoreText.text = "Score SHIT";
|
||||
lerpScore = Math.floor(FlxMath.lerp(lerpScore, intendedScore, 0.5));
|
||||
|
||||
scoreText.text = "WEEK SCORE:" + lerpScore;
|
||||
// FlxG.watch.addQuick('font', scoreText.font);
|
||||
|
||||
difficultySelectors.visible = weekUnlocked[curWeek];
|
||||
@@ -245,6 +247,8 @@ class StoryMenuState extends MusicBeatState
|
||||
PlayState.storyDifficulty = curDifficulty;
|
||||
|
||||
PlayState.SONG = Song.loadFromJson(PlayState.storyPlaylist[0].toLowerCase() + diffic, PlayState.storyPlaylist[0].toLowerCase());
|
||||
PlayState.storyWeek = curWeek;
|
||||
PlayState.campaignScore = 0;
|
||||
new FlxTimer().start(1, function(tmr:FlxTimer)
|
||||
{
|
||||
if (FlxG.sound.music != null)
|
||||
@@ -282,10 +286,14 @@ class StoryMenuState extends MusicBeatState
|
||||
|
||||
// USING THESE WEIRD VALUES SO THAT IT DOESNT FLOAT UP
|
||||
sprDifficulty.y = leftArrow.y - 15;
|
||||
intendedScore = Highscore.getWeekScore(curWeek, curDifficulty);
|
||||
|
||||
FlxTween.tween(sprDifficulty, {y: leftArrow.y + 15, alpha: 1}, 0.07);
|
||||
}
|
||||
|
||||
var lerpScore:Int = 0;
|
||||
var intendedScore:Int = 0;
|
||||
|
||||
function changeWeek(change:Int = 0):Void
|
||||
{
|
||||
curWeek += change;
|
||||
@@ -300,6 +308,10 @@ class StoryMenuState extends MusicBeatState
|
||||
for (item in grpWeekText.members)
|
||||
{
|
||||
item.targetY = bullShit - curWeek;
|
||||
if (item.targetY == Std.int(0) && weekUnlocked[curWeek])
|
||||
item.alpha = 1;
|
||||
else
|
||||
item.alpha = 0.6;
|
||||
bullShit++;
|
||||
}
|
||||
|
||||
@@ -326,5 +338,7 @@ class StoryMenuState extends MusicBeatState
|
||||
|
||||
txtTracklist.screenCenter(X);
|
||||
txtTracklist.x -= FlxG.width * 0.35;
|
||||
|
||||
intendedScore = Highscore.getWeekScore(curWeek, curDifficulty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,11 +13,14 @@ import flixel.group.FlxGroup;
|
||||
import flixel.input.gamepad.FlxGamepad;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.system.FlxSound;
|
||||
import flixel.system.ui.FlxSoundTray;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.tweens.FlxEase;
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.util.FlxTimer;
|
||||
import lime.utils.Assets;
|
||||
|
||||
class TitleState extends MusicBeatState
|
||||
{
|
||||
@@ -30,16 +33,10 @@ class TitleState extends MusicBeatState
|
||||
var textGroup:FlxGroup;
|
||||
var ngSpr:FlxSprite;
|
||||
|
||||
var wackyIntros:Array<Array<String>> = [
|
||||
['Shoutouts to tom fulp', 'lmao'], ["Ludum dare", "extraordinaire"], ['Cyberzone', 'coming soon'], ['love to thriftman', 'swag'],
|
||||
['ULTIMATE RHYTHM GAMING', 'probably'], ['DOPE ASS GAME', 'playstation magazine'], ['in loving memory of', 'henryeyes'], ['dancin', 'forever'],
|
||||
['Ritz dx', 'rest in peace'], ['rate five', 'pls no blam'], ['rhythm gaming', 'ultimate'], ['game of the year', 'forever'],
|
||||
['you already know', 'we really out here'], ['rise and grind', 'love to luis'], ['like parappa', 'but cooler'],
|
||||
['album of the year', 'chuckie finster'], ["free gitaroo man", "with love to wandaboy"], ['better than geometry dash', 'fight me robtop'],
|
||||
['kiddbrute for president', 'vote now']];
|
||||
|
||||
var curWacky:Array<String> = [];
|
||||
|
||||
var wackyImage:FlxSprite;
|
||||
|
||||
override public function create():Void
|
||||
{
|
||||
#if (!web)
|
||||
@@ -48,18 +45,30 @@ class TitleState extends MusicBeatState
|
||||
|
||||
PlayerSettings.init();
|
||||
|
||||
curWacky = FlxG.random.getObject(wackyIntros);
|
||||
curWacky = FlxG.random.getObject(getIntroTextShit());
|
||||
|
||||
// DEBUG BULLSHIT
|
||||
|
||||
super.create();
|
||||
|
||||
#if (!debug && NG_LOGIN)
|
||||
#if (!switch && !debug && NG_LOGIN)
|
||||
var ng:NGio = new NGio(APIStuff.API, APIStuff.EncKey);
|
||||
#end
|
||||
|
||||
FlxG.save.bind('funkin', 'ninjamuffin99');
|
||||
|
||||
Highscore.load();
|
||||
|
||||
if (FlxG.save.data.weekUnlocked != null)
|
||||
{
|
||||
StoryMenuState.weekUnlocked = FlxG.save.data.weekUnlocked;
|
||||
|
||||
if (StoryMenuState.weekUnlocked.length < 3)
|
||||
StoryMenuState.weekUnlocked.insert(0, true);
|
||||
}
|
||||
|
||||
#if SKIP_TO_PLAYSTATE
|
||||
FlxG.switchState(new StoryMenuState());
|
||||
FlxG.switchState(new FreeplayState());
|
||||
#else
|
||||
startIntro();
|
||||
#end
|
||||
@@ -89,6 +98,10 @@ class TitleState extends MusicBeatState
|
||||
transIn = FlxTransitionableState.defaultTransIn;
|
||||
transOut = FlxTransitionableState.defaultTransOut;
|
||||
|
||||
// var music:FlxSound = new FlxSound();
|
||||
// music.loadStream('assets/music/freakyMenu' + TitleState.soundExt);
|
||||
// FlxG.sound.list.add(music);
|
||||
// music.play();
|
||||
FlxG.sound.playMusic('assets/music/freakyMenu' + TitleState.soundExt, 0);
|
||||
|
||||
FlxG.sound.music.fadeIn(4, 0, 0.7);
|
||||
@@ -172,11 +185,32 @@ class TitleState extends MusicBeatState
|
||||
// credGroup.add(credTextShit);
|
||||
}
|
||||
|
||||
function getIntroTextShit():Array<Array<String>>
|
||||
{
|
||||
var fullText:String = Assets.getText('assets/data/introText.txt');
|
||||
|
||||
var firstArray:Array<String> = fullText.split('\n');
|
||||
var swagGoodArray:Array<Array<String>> = [];
|
||||
|
||||
for (i in firstArray)
|
||||
{
|
||||
swagGoodArray.push(i.split('--'));
|
||||
}
|
||||
|
||||
return swagGoodArray;
|
||||
}
|
||||
|
||||
var transitioning:Bool = false;
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
Conductor.songPosition = FlxG.sound.music.time;
|
||||
// FlxG.watch.addQuick('amp', FlxG.sound.music.amplitude);
|
||||
|
||||
if (FlxG.keys.justPressed.F)
|
||||
{
|
||||
FlxG.fullscreen = !FlxG.fullscreen;
|
||||
}
|
||||
|
||||
var pressedEnter:Bool = FlxG.keys.justPressed.ENTER;
|
||||
|
||||
@@ -190,7 +224,14 @@ class TitleState extends MusicBeatState
|
||||
|
||||
if (pressedEnter && !transitioning && skippedIntro)
|
||||
{
|
||||
#if !switch
|
||||
NGio.unlockMedal(60960);
|
||||
|
||||
// If it's Friday according to da clock
|
||||
if (Date.now().getDay() == 5)
|
||||
NGio.unlockMedal(61034);
|
||||
#end
|
||||
|
||||
titleText.animation.play('press');
|
||||
|
||||
FlxG.camera.flash(FlxColor.WHITE, 1);
|
||||
|
||||
@@ -1,227 +0,0 @@
|
||||
package io.newgrounds;
|
||||
|
||||
import io.newgrounds.utils.Dispatcher;
|
||||
import io.newgrounds.utils.AsyncHttp;
|
||||
import io.newgrounds.objects.Error;
|
||||
import io.newgrounds.objects.events.Result;
|
||||
import io.newgrounds.objects.events.Result.ResultBase;
|
||||
import io.newgrounds.objects.events.Response;
|
||||
|
||||
import haxe.ds.StringMap;
|
||||
import haxe.Json;
|
||||
|
||||
/** A generic way to handle calls agnostic to their type */
|
||||
interface ICallable {
|
||||
|
||||
public var component(default, null):String;
|
||||
|
||||
public function send():Void;
|
||||
public function queue():Void;
|
||||
public function destroy():Void;
|
||||
}
|
||||
|
||||
class Call<T:ResultBase>
|
||||
implements ICallable {
|
||||
|
||||
public var component(default, null):String;
|
||||
|
||||
var _core:NGLite;
|
||||
var _properties:StringMap<Dynamic>;
|
||||
var _parameters:StringMap<Dynamic>;
|
||||
var _requireSession:Bool;
|
||||
var _isSecure:Bool;
|
||||
|
||||
// --- BASICALLY SIGNALS
|
||||
var _dataHandlers:TypedDispatcher<Response<T>>;
|
||||
var _successHandlers:Dispatcher;
|
||||
var _httpErrorHandlers:TypedDispatcher<Error>;
|
||||
var _statusHandlers:TypedDispatcher<Int>;
|
||||
|
||||
public function new (core:NGLite, component:String, requireSession:Bool = false, isSecure:Bool = false) {
|
||||
|
||||
_core = core;
|
||||
this.component = component;
|
||||
_requireSession = requireSession;
|
||||
_isSecure = isSecure && core.encryptionHandler != null;
|
||||
}
|
||||
|
||||
/** adds a property to the input's object. **/
|
||||
public function addProperty(name:String, value:Dynamic):Call<T> {
|
||||
|
||||
if (_properties == null)
|
||||
_properties = new StringMap<Dynamic>();
|
||||
|
||||
_properties.set(name, value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/** adds a parameter to the call's component object. **/
|
||||
public function addComponentParameter(name:String, value:Dynamic, defaultValue:Dynamic = null):Call<T> {
|
||||
|
||||
if (value == defaultValue)//TODO?: allow sending null value
|
||||
return this;
|
||||
|
||||
if (_parameters == null)
|
||||
_parameters = new StringMap<Dynamic>();
|
||||
|
||||
_parameters.set(name, value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Handy callback setter for chained call modifiers. Called when ng.io replies successfully */
|
||||
public function addDataHandler(handler:Response<T>->Void):Call<T> {
|
||||
|
||||
if (_dataHandlers == null)
|
||||
_dataHandlers = new TypedDispatcher<Response<T>>();
|
||||
|
||||
_dataHandlers.add(handler);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Handy callback setter for chained call modifiers. Called when ng.io replies successfully */
|
||||
public function addSuccessHandler(handler:Void->Void):Call<T> {
|
||||
|
||||
if (_successHandlers == null)
|
||||
_successHandlers = new Dispatcher();
|
||||
|
||||
_successHandlers.add(handler);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Handy callback setter for chained call modifiers. Called when ng.io does not reply for any reason */
|
||||
public function addErrorHandler(handler:Error->Void):Call<T> {
|
||||
|
||||
if (_httpErrorHandlers == null)
|
||||
_httpErrorHandlers = new TypedDispatcher<Error>();
|
||||
|
||||
_httpErrorHandlers.add(handler);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Handy callback setter for chained call modifiers. No idea when this is called; */
|
||||
public function addStatusHandler(handler:Int->Void):Call<T> {//TODO:learn what this is for
|
||||
|
||||
if (_statusHandlers == null)
|
||||
_statusHandlers = new TypedDispatcher<Int>();
|
||||
|
||||
_statusHandlers.add(handler);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the call to the server, do not modify this object after calling this
|
||||
* @param secure If encryption is enabled, it will encrypt the call.
|
||||
**/
|
||||
public function send():Void {
|
||||
|
||||
var data:Dynamic = {};
|
||||
data.app_id = _core.appId;
|
||||
data.call = {};
|
||||
data.call.component = component;
|
||||
|
||||
if (_core.debug)
|
||||
addProperty("debug", true);
|
||||
|
||||
if (_properties == null || !_properties.exists("session_id")) {
|
||||
// --- HAS NO SESSION ID
|
||||
|
||||
if (_core.sessionId != null) {
|
||||
// --- AUTO ADD SESSION ID
|
||||
|
||||
addProperty("session_id", _core.sessionId);
|
||||
|
||||
} else if (_requireSession){
|
||||
|
||||
_core.logError(new Error('cannot send "$component" call without a sessionId'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_properties != null) {
|
||||
|
||||
for (field in _properties.keys())
|
||||
Reflect.setField(data, field, _properties.get(field));
|
||||
}
|
||||
|
||||
if (_parameters != null) {
|
||||
|
||||
data.call.parameters = {};
|
||||
|
||||
for (field in _parameters.keys())
|
||||
Reflect.setField(data.call.parameters, field, _parameters.get(field));
|
||||
}
|
||||
|
||||
_core.logVerbose('Post - ${Json.stringify(data)}');
|
||||
|
||||
if (_isSecure) {
|
||||
|
||||
var secureData = _core.encryptionHandler(Json.stringify(data.call));
|
||||
data.call = {};
|
||||
data.call.secure = secureData;
|
||||
|
||||
_core.logVerbose(' secure - $secureData');
|
||||
}
|
||||
|
||||
_core.markCallPending(this);
|
||||
|
||||
AsyncHttp.send(_core, Json.stringify(data), onData, onHttpError, onStatus);
|
||||
}
|
||||
|
||||
/** Adds the call to the queue */
|
||||
public function queue():Void {
|
||||
|
||||
_core.queueCall(this);
|
||||
}
|
||||
|
||||
function onData(reply:String):Void {
|
||||
|
||||
_core.logVerbose('Reply - $reply');
|
||||
|
||||
if (_dataHandlers == null && _successHandlers == null)
|
||||
return;
|
||||
|
||||
var response = new Response<T>(_core, reply);
|
||||
|
||||
if (_dataHandlers != null)
|
||||
_dataHandlers.dispatch(response);
|
||||
|
||||
if (response.success && response.result.success && _successHandlers != null)
|
||||
_successHandlers.dispatch();
|
||||
|
||||
destroy();
|
||||
}
|
||||
|
||||
function onHttpError(message:String):Void {
|
||||
|
||||
_core.logError(message);
|
||||
|
||||
if (_httpErrorHandlers == null)
|
||||
return;
|
||||
|
||||
var error = new Error(message);
|
||||
_httpErrorHandlers.dispatch(error);
|
||||
}
|
||||
|
||||
function onStatus(status:Int):Void {
|
||||
|
||||
if (_statusHandlers == null)
|
||||
return;
|
||||
|
||||
_statusHandlers.dispatch(status);
|
||||
}
|
||||
|
||||
public function destroy():Void {
|
||||
|
||||
_core = null;
|
||||
|
||||
_properties = null;
|
||||
_parameters = null;
|
||||
|
||||
_dataHandlers = null;
|
||||
_successHandlers = null;
|
||||
_httpErrorHandlers = null;
|
||||
_statusHandlers = null;
|
||||
}
|
||||
}
|
||||
@@ -1,475 +0,0 @@
|
||||
package io.newgrounds;
|
||||
|
||||
#if ng_lite
|
||||
typedef NG = NGLite; //TODO: test and make lite UI
|
||||
#else
|
||||
import io.newgrounds.utils.Dispatcher;
|
||||
import io.newgrounds.objects.Error;
|
||||
import io.newgrounds.objects.events.Result.SessionResult;
|
||||
import io.newgrounds.objects.events.Result.MedalListResult;
|
||||
import io.newgrounds.objects.events.Result.ScoreBoardResult;
|
||||
import io.newgrounds.objects.events.Response;
|
||||
import io.newgrounds.objects.User;
|
||||
import io.newgrounds.objects.Medal;
|
||||
import io.newgrounds.objects.Session;
|
||||
import io.newgrounds.objects.ScoreBoard;
|
||||
|
||||
import haxe.ds.IntMap;
|
||||
import haxe.Timer;
|
||||
|
||||
/**
|
||||
* The Newgrounds API for Haxe.
|
||||
* Contains many things ripped from MSGhero
|
||||
* - https://github.com/MSGhero/NG.hx
|
||||
* @author GeoKureli
|
||||
*/
|
||||
class NG extends NGLite {
|
||||
|
||||
static public var core(default, null):NG;
|
||||
static public var onCoreReady(default, null):Dispatcher = new Dispatcher();
|
||||
|
||||
// --- DATA
|
||||
|
||||
/** The logged in user */
|
||||
public var user(get, never):User;
|
||||
function get_user():User {
|
||||
|
||||
if (_session == null)
|
||||
return null;
|
||||
|
||||
return _session.user;
|
||||
}
|
||||
public var passportUrl(get, never):String;
|
||||
function get_passportUrl():String {
|
||||
|
||||
if (_session == null || _session.status != SessionStatus.REQUEST_LOGIN)
|
||||
return null;
|
||||
|
||||
return _session.passportUrl;
|
||||
}
|
||||
public var medals(default, null):IntMap<Medal>;
|
||||
public var scoreBoards(default, null):IntMap<ScoreBoard>;
|
||||
|
||||
// --- EVENTS
|
||||
|
||||
public var onLogin(default, null):Dispatcher;
|
||||
public var onLogOut(default, null):Dispatcher;
|
||||
public var onMedalsLoaded(default, null):Dispatcher;
|
||||
public var onScoreBoardsLoaded(default, null):Dispatcher;
|
||||
|
||||
// --- MISC
|
||||
|
||||
public var loggedIn(default, null):Bool;
|
||||
public var attemptingLogin(default, null):Bool;
|
||||
|
||||
var _loginCancelled:Bool;
|
||||
var _passportCallback:Void->Void;
|
||||
|
||||
var _session:Session;
|
||||
|
||||
/**
|
||||
* Iniitializes the API, call before utilizing any other component
|
||||
* @param appId The unique ID of your app as found in the 'API Tools' tab of your Newgrounds.com project.
|
||||
* @param sessionId A unique session id used to identify the active user.
|
||||
**/
|
||||
public function new(appId = "test", sessionId:String = null, ?onSessionFail:Error->Void) {
|
||||
|
||||
_session = new Session(this);
|
||||
onLogin = new Dispatcher();
|
||||
onLogOut = new Dispatcher();
|
||||
onMedalsLoaded = new Dispatcher();
|
||||
onScoreBoardsLoaded = new Dispatcher();
|
||||
|
||||
attemptingLogin = sessionId != null;
|
||||
|
||||
super(appId, sessionId, onSessionFail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates NG.core, the heart and soul of the API. This is not the only way to create an instance,
|
||||
* nor is NG a forced singleton, but it's the only way to set the static NG.core.
|
||||
**/
|
||||
static public function create(appId = "test", sessionId:String = null, ?onSessionFail:Error->Void):Void {
|
||||
|
||||
core = new NG(appId, sessionId, onSessionFail);
|
||||
|
||||
onCoreReady.dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates NG.core, and tries to create a session. This is not the only way to create an instance,
|
||||
* nor is NG a forced singleton, but it's the only way to set the static NG.core.
|
||||
**/
|
||||
static public function createAndCheckSession
|
||||
( appId = "test"
|
||||
, backupSession:String = null
|
||||
, ?onSessionFail:Error->Void
|
||||
):Void {
|
||||
|
||||
var session = NGLite.getSessionId();
|
||||
if (session == null)
|
||||
session = backupSession;
|
||||
|
||||
create(appId, session, onSessionFail);
|
||||
|
||||
core.host = getHost();
|
||||
if (core.sessionId != null)
|
||||
core.attemptingLogin = true;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// APP
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
override function checkInitialSession(failHandler:Error->Void, response:Response<SessionResult>):Void {
|
||||
|
||||
onSessionReceive(response, null, null, failHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins the login process
|
||||
*
|
||||
* @param onSuccess Called when the login is a success
|
||||
* @param onPending Called when the passportUrl has been identified, call NG.core.openPassportLink
|
||||
* to open the link continue the process. Leave as null to open the url automatically
|
||||
* NOTE: Browser games must open links on click events or else it will be blocked by
|
||||
* the popup blocker.
|
||||
* @param onFail
|
||||
* @param onCancel Called when the user denies the passport connection.
|
||||
*/
|
||||
public function requestLogin
|
||||
( onSuccess:Void->Void = null
|
||||
, onPending:Void->Void = null
|
||||
, onFail :Error->Void = null
|
||||
, onCancel :Void->Void = null
|
||||
):Void {
|
||||
|
||||
if (attemptingLogin) {
|
||||
|
||||
logError("cannot request another login until the previous attempt is complete");
|
||||
return;
|
||||
}
|
||||
|
||||
if (loggedIn) {
|
||||
|
||||
logError("cannot log in, already logged in");
|
||||
return;
|
||||
}
|
||||
|
||||
attemptingLogin = true;
|
||||
_loginCancelled = false;
|
||||
_passportCallback = null;
|
||||
|
||||
var call = calls.app.startSession(true)
|
||||
.addDataHandler(onSessionReceive.bind(_, onSuccess, onPending, onFail, onCancel));
|
||||
|
||||
if (onFail != null)
|
||||
call.addErrorHandler(onFail);
|
||||
|
||||
call.send();
|
||||
}
|
||||
|
||||
function onSessionReceive
|
||||
( response :Response<SessionResult>
|
||||
, onSuccess:Void->Void = null
|
||||
, onPending:Void->Void = null
|
||||
, onFail :Error->Void = null
|
||||
, onCancel :Void->Void = null
|
||||
):Void {
|
||||
|
||||
if (!response.success || !response.result.success) {
|
||||
|
||||
sessionId = null;
|
||||
endLoginAndCall(null);
|
||||
|
||||
if (onFail != null)
|
||||
onFail(!response.success ? response.error : response.result.error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_session.parse(response.result.data.session);
|
||||
sessionId = _session.id;
|
||||
|
||||
logVerbose('session started - status: ${_session.status}');
|
||||
|
||||
if (_session.status == SessionStatus.REQUEST_LOGIN) {
|
||||
|
||||
_passportCallback = checkSession.bind(null, onSuccess, onCancel);
|
||||
if (onPending != null)
|
||||
onPending();
|
||||
else
|
||||
openPassportUrl();
|
||||
|
||||
} else
|
||||
checkSession(null, onSuccess, onCancel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this once the passport link is established and it will load the passport URL and
|
||||
* start checking for session connect periodically
|
||||
*/
|
||||
public function openPassportUrl():Void {
|
||||
|
||||
if (passportUrl != null) {
|
||||
|
||||
logVerbose('loading passport: ${passportUrl}');
|
||||
openPassportHelper(passportUrl);
|
||||
onPassportUrlOpen();
|
||||
|
||||
} else
|
||||
logError("Cannot open passport");
|
||||
}
|
||||
|
||||
|
||||
static function openPassportHelper(url:String):Void {
|
||||
var window = "_blank";
|
||||
|
||||
#if flash
|
||||
flash.Lib.getURL(new flash.net.URLRequest(url), window);
|
||||
#elseif (js && html5)
|
||||
js.Browser.window.open(url, window);
|
||||
#elseif desktop
|
||||
|
||||
#if (sys && windows)
|
||||
Sys.command("start", ["", url]);
|
||||
#elseif mac
|
||||
Sys.command("/usr/bin/open", [url]);
|
||||
#elseif linux
|
||||
Sys.command("/usr/bin/xdg-open", [path, "&"]);
|
||||
#end
|
||||
|
||||
#elseif android
|
||||
JNI.createStaticMethod
|
||||
( "org/haxe/lime/GameActivity"
|
||||
, "openURL"
|
||||
, "(Ljava/lang/String;Ljava/lang/String;)V"
|
||||
) (url, window);
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this once the passport link is established and it will start checking for session connect periodically
|
||||
*/
|
||||
public function onPassportUrlOpen():Void {
|
||||
|
||||
if (_passportCallback != null)
|
||||
_passportCallback();
|
||||
|
||||
_passportCallback = null;
|
||||
}
|
||||
|
||||
function checkSession(response:Response<SessionResult>, onSucceess:Void->Void, onCancel:Void->Void):Void {
|
||||
|
||||
if (response != null) {
|
||||
|
||||
if (!response.success || !response.result.success) {
|
||||
|
||||
log("login cancelled via passport");
|
||||
|
||||
endLoginAndCall(onCancel);
|
||||
return;
|
||||
}
|
||||
|
||||
_session.parse(response.result.data.session);
|
||||
}
|
||||
|
||||
if (_session.status == SessionStatus.USER_LOADED) {
|
||||
|
||||
loggedIn = true;
|
||||
endLoginAndCall(onSucceess);
|
||||
onLogin.dispatch();
|
||||
|
||||
} else if (_session.status == SessionStatus.REQUEST_LOGIN){
|
||||
|
||||
var call = calls.app.checkSession()
|
||||
.addDataHandler(checkSession.bind(_, onSucceess, onCancel));
|
||||
|
||||
// Wait 3 seconds and try again
|
||||
timer(3.0,
|
||||
function():Void {
|
||||
|
||||
// Check if cancelLoginRequest was called
|
||||
if (!_loginCancelled)
|
||||
call.send();
|
||||
else {
|
||||
|
||||
log("login cancelled via cancelLoginRequest");
|
||||
endLoginAndCall(onCancel);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
} else
|
||||
// The user cancelled the passport
|
||||
endLoginAndCall(onCancel);
|
||||
}
|
||||
|
||||
public function cancelLoginRequest():Void {
|
||||
|
||||
if (attemptingLogin)
|
||||
_loginCancelled = true;
|
||||
}
|
||||
|
||||
function endLoginAndCall(callback:Void->Void):Void {
|
||||
|
||||
attemptingLogin = false;
|
||||
_loginCancelled = false;
|
||||
|
||||
if (callback != null)
|
||||
callback();
|
||||
}
|
||||
|
||||
public function logOut(onComplete:Void->Void = null):Void {
|
||||
|
||||
var call = calls.app.endSession()
|
||||
.addSuccessHandler(onLogOutSuccessful);
|
||||
|
||||
if (onComplete != null)
|
||||
call.addSuccessHandler(onComplete);
|
||||
|
||||
call.addSuccessHandler(onLogOut.dispatch)
|
||||
.send();
|
||||
}
|
||||
|
||||
function onLogOutSuccessful():Void {
|
||||
|
||||
_session.expire();
|
||||
sessionId = null;
|
||||
loggedIn = false;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// MEDALS
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
public function requestMedals(onSuccess:Void->Void = null, onFail:Error->Void = null):Void {
|
||||
|
||||
var call = calls.medal.getList()
|
||||
.addDataHandler(onMedalsReceived);
|
||||
|
||||
if (onSuccess != null)
|
||||
call.addSuccessHandler(onSuccess);
|
||||
|
||||
if (onFail != null)
|
||||
call.addErrorHandler(onFail);
|
||||
|
||||
call.send();
|
||||
}
|
||||
|
||||
function onMedalsReceived(response:Response<MedalListResult>):Void {
|
||||
|
||||
if (!response.success || !response.result.success)
|
||||
return;
|
||||
|
||||
var idList:Array<Int> = new Array<Int>();
|
||||
|
||||
if (medals == null) {
|
||||
|
||||
medals = new IntMap<Medal>();
|
||||
|
||||
for (medalData in response.result.data.medals) {
|
||||
|
||||
var medal = new Medal(this, medalData);
|
||||
medals.set(medal.id, medal);
|
||||
idList.push(medal.id);
|
||||
}
|
||||
} else {
|
||||
|
||||
for (medalData in response.result.data.medals) {
|
||||
|
||||
medals.get(medalData.id).parse(medalData);
|
||||
idList.push(medalData.id);
|
||||
}
|
||||
}
|
||||
|
||||
logVerbose('${response.result.data.medals.length} Medals received [${idList.join(", ")}]');
|
||||
|
||||
onMedalsLoaded.dispatch();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// SCOREBOARDS
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
public function requestScoreBoards(onSuccess:Void->Void = null, onFail:Error->Void = null):Void {
|
||||
|
||||
if (scoreBoards != null) {
|
||||
|
||||
log("aborting scoreboard request, all scoreboards are loaded");
|
||||
|
||||
if (onSuccess != null)
|
||||
onSuccess();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var call = calls.scoreBoard.getBoards()
|
||||
.addDataHandler(onBoardsReceived);
|
||||
|
||||
if (onSuccess != null)
|
||||
call.addSuccessHandler(onSuccess);
|
||||
|
||||
if (onFail != null)
|
||||
call.addErrorHandler(onFail);
|
||||
|
||||
call.send();
|
||||
}
|
||||
|
||||
function onBoardsReceived(response:Response<ScoreBoardResult>):Void {
|
||||
|
||||
if (!response.success || !response.result.success)
|
||||
return;
|
||||
|
||||
var idList:Array<Int> = new Array<Int>();
|
||||
|
||||
if (scoreBoards == null) {
|
||||
|
||||
scoreBoards = new IntMap<ScoreBoard>();
|
||||
|
||||
for (boardData in response.result.data.scoreboards) {
|
||||
|
||||
var board = new ScoreBoard(this, boardData);
|
||||
scoreBoards.set(board.id, board);
|
||||
idList.push(board.id);
|
||||
}
|
||||
}
|
||||
|
||||
logVerbose('${response.result.data.scoreboards.length} ScoreBoards received [${idList.join(", ")}]');
|
||||
|
||||
onScoreBoardsLoaded.dispatch();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// HELPERS
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
function timer(delay:Float, callback:Void->Void):Void {
|
||||
|
||||
var timer = new Timer(Std.int(delay * 1000));
|
||||
timer.run = function func():Void {
|
||||
|
||||
timer.stop();
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
static var urlParser:EReg = ~/^(?:http[s]?:\/\/)?([^:\/\s]+)(:[0-9]+)?((?:\/\w+)*\/)([\w\-\.]+[^#?\s]+)([^#\s]*)?(#[\w\-]+)?$/i;//TODO:trim
|
||||
/** Used to get the current web host of your game. */
|
||||
static public function getHost():String {
|
||||
|
||||
var url = NGLite.getUrl();
|
||||
|
||||
if (url == null || url == "")
|
||||
return "<AppView>";
|
||||
|
||||
if (url.indexOf("file") == 0)
|
||||
return "<LocalHost>";
|
||||
|
||||
if (urlParser.match(url))
|
||||
return urlParser.matched(1);
|
||||
|
||||
return "<Unknown>";
|
||||
}
|
||||
}
|
||||
#end
|
||||
@@ -1,287 +0,0 @@
|
||||
package io.newgrounds;
|
||||
|
||||
import haxe.crypto.Base64;
|
||||
import haxe.io.Bytes;
|
||||
import haxe.PosInfos;
|
||||
|
||||
import io.newgrounds.Call.ICallable;
|
||||
import io.newgrounds.components.ComponentList;
|
||||
import io.newgrounds.crypto.EncryptionFormat;
|
||||
import io.newgrounds.crypto.Cipher;
|
||||
import io.newgrounds.crypto.Rc4;
|
||||
import io.newgrounds.objects.Error;
|
||||
import io.newgrounds.objects.events.Response;
|
||||
import io.newgrounds.objects.events.Result.ResultBase;
|
||||
import io.newgrounds.objects.events.Result.SessionResult;
|
||||
import io.newgrounds.utils.Dispatcher;
|
||||
|
||||
#if !(html5 || flash || desktop || neko)
|
||||
#error "Target not supported, use: Flash, JS/HTML5, cpp or maybe neko";
|
||||
#end
|
||||
|
||||
/**
|
||||
* The barebones NG.io API. Allows API calls with code completion
|
||||
* and retrieves server data via strongly typed Objects
|
||||
*
|
||||
* Contains many things ripped from MSGhero's repo
|
||||
* - https://github.com/MSGhero/NG.hx
|
||||
*
|
||||
* @author GeoKureli
|
||||
*/
|
||||
class NGLite {
|
||||
|
||||
static public var core(default, null):NGLite;
|
||||
static public var onCoreReady(default, null):Dispatcher = new Dispatcher();
|
||||
|
||||
/** Enables verbose logging */
|
||||
public var verbose:Bool;
|
||||
public var debug:Bool;
|
||||
/** The unique ID of your app as found in the 'API Tools' tab of your Newgrounds.com project. */
|
||||
public var appId(default, null):String;
|
||||
/** The name of the host the game is being played on */
|
||||
public var host:String;
|
||||
|
||||
@:isVar
|
||||
public var sessionId(default, set):String;
|
||||
function set_sessionId(value:String):String {
|
||||
|
||||
return this.sessionId = value == "" ? null : value;
|
||||
}
|
||||
|
||||
/** Components used to call the NG server directly */
|
||||
public var calls(default, null):ComponentList;
|
||||
|
||||
/**
|
||||
* Converts an object to an encrypted string that can be decrypted by the server.
|
||||
* Set your preffered encrypter here,
|
||||
* or just call setDefaultEcryptionHandler with your app's encryption settings
|
||||
**/
|
||||
public var encryptionHandler:String->String;
|
||||
|
||||
/**
|
||||
* Iniitializes the API, call before utilizing any other component
|
||||
* @param appId The unique ID of your app as found in the 'API Tools' tab of your Newgrounds.com project.
|
||||
* @param sessionId A unique session id used to identify the active user.
|
||||
**/
|
||||
public function new(appId = "test", sessionId:String = null, ?onSessionFail:Error->Void) {
|
||||
|
||||
this.appId = appId;
|
||||
this.sessionId = sessionId;
|
||||
|
||||
calls = new ComponentList(this);
|
||||
|
||||
if (this.sessionId != null) {
|
||||
|
||||
calls.app.checkSession()
|
||||
.addDataHandler(checkInitialSession.bind(onSessionFail))
|
||||
.addErrorHandler(initialSessionFail.bind(onSessionFail))
|
||||
.send();
|
||||
}
|
||||
}
|
||||
|
||||
function checkInitialSession(onFail:Error->Void, response:Response<SessionResult>):Void {
|
||||
|
||||
if (!response.success || !response.result.success || response.result.data.session.expired) {
|
||||
|
||||
initialSessionFail(onFail, response.success ? response.result.error : response.error);
|
||||
}
|
||||
}
|
||||
|
||||
function initialSessionFail(onFail:Error->Void, error:Error):Void {
|
||||
|
||||
sessionId = null;
|
||||
|
||||
if (onFail != null)
|
||||
onFail(error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates NG.core, the heart and soul of the API. This is not the only way to create an instance,
|
||||
* nor is NG a forced singleton, but it's the only way to set the static NG.core.
|
||||
**/
|
||||
static public function create(appId = "test", sessionId:String = null, ?onSessionFail:Error->Void):Void {
|
||||
|
||||
core = new NGLite(appId, sessionId, onSessionFail);
|
||||
|
||||
onCoreReady.dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates NG.core, and tries to create a session. This is not the only way to create an instance,
|
||||
* nor is NG a forced singleton, but it's the only way to set the static NG.core.
|
||||
**/
|
||||
static public function createAndCheckSession
|
||||
( appId = "test"
|
||||
, backupSession:String = null
|
||||
, ?onSessionFail:Error->Void
|
||||
):Void {
|
||||
|
||||
var session = getSessionId();
|
||||
if (session == null)
|
||||
session = backupSession;
|
||||
|
||||
create(appId, session, onSessionFail);
|
||||
}
|
||||
|
||||
inline static public function getUrl():String {
|
||||
|
||||
#if html5
|
||||
return js.Browser.document.location.href;
|
||||
#elseif flash
|
||||
return flash.Lib.current.stage.loaderInfo != null
|
||||
? flash.Lib.current.stage.loaderInfo.url
|
||||
: null;
|
||||
#else
|
||||
return null;
|
||||
#end
|
||||
}
|
||||
|
||||
static public function getSessionId():String {
|
||||
|
||||
#if html5
|
||||
|
||||
var url = getUrl();
|
||||
|
||||
// Check for URL params
|
||||
var index = url.indexOf("?");
|
||||
if (index != -1) {
|
||||
|
||||
// Check for session ID in params
|
||||
for (param in url.substr(index + 1).split("&")) {
|
||||
|
||||
index = param.indexOf("=");
|
||||
if (index != -1 && param.substr(0, index) == "ngio_session_id")
|
||||
return param.substr(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
#elseif flash
|
||||
|
||||
if (flash.Lib.current.stage.loaderInfo != null
|
||||
&& Reflect.hasField(flash.Lib.current.stage.loaderInfo.parameters, "ngio_session_id"))
|
||||
return Reflect.field(flash.Lib.current.stage.loaderInfo.parameters, "ngio_session_id");
|
||||
|
||||
#end
|
||||
|
||||
return null;
|
||||
|
||||
// --- EXAMPLE LOADER PARAMS
|
||||
//{ "1517703669" : ""
|
||||
//, "ng_username" : "GeoKureli"
|
||||
//, "NewgroundsAPI_SessionID" : "F1LusbG6P8Qf91w7zeUE37c1752563f366688ac6153996d12eeb111a2f60w2xn"
|
||||
//, "NewgroundsAPI_PublisherID" : 1
|
||||
//, "NewgroundsAPI_UserID" : 488329
|
||||
//, "NewgroundsAPI_SandboxID" : "5a76520e4ae1e"
|
||||
//, "ngio_session_id" : "0c6c4e02567a5116734ba1a0cd841dac28a42e79302290"
|
||||
//, "NewgroundsAPI_UserName" : "GeoKureli"
|
||||
//}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// CALLS
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
var _queuedCalls:Array<ICallable> = new Array<ICallable>();
|
||||
var _pendingCalls:Array<ICallable> = new Array<ICallable>();
|
||||
|
||||
@:allow(io.newgrounds.Call)
|
||||
@:generic
|
||||
function queueCall<T:ResultBase>(call:Call<T>):Void {
|
||||
|
||||
logVerbose('queued - ${call.component}');
|
||||
|
||||
_queuedCalls.push(call);
|
||||
checkQueue();
|
||||
}
|
||||
|
||||
@:allow(io.newgrounds.Call)
|
||||
@:generic
|
||||
function markCallPending<T:ResultBase>(call:Call<T>):Void {
|
||||
|
||||
_pendingCalls.push(call);
|
||||
|
||||
call.addDataHandler(function (_):Void { onCallComplete(call); });
|
||||
call.addErrorHandler(function (_):Void { onCallComplete(call); });
|
||||
}
|
||||
|
||||
function onCallComplete(call:ICallable):Void {
|
||||
|
||||
_pendingCalls.remove(call);
|
||||
checkQueue();
|
||||
}
|
||||
|
||||
function checkQueue():Void {
|
||||
|
||||
if (_pendingCalls.length == 0 && _queuedCalls.length > 0)
|
||||
_queuedCalls.shift().send();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// LOGGING / ERRORS
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
/** Called internally, set this to your preferred logging method */
|
||||
dynamic public function log(any:Dynamic, ?pos:PosInfos):Void {//TODO: limit access via @:allow
|
||||
|
||||
haxe.Log.trace('[Newgrounds API] :: ${any}', pos);
|
||||
}
|
||||
|
||||
/** used internally, logs if verbose is true */
|
||||
inline public function logVerbose(any:Dynamic, ?pos:PosInfos):Void {//TODO: limit access via @:allow
|
||||
|
||||
if (verbose)
|
||||
log(any, pos);
|
||||
}
|
||||
|
||||
/** Used internally. Logs by default, set this to your preferred error handling method */
|
||||
dynamic public function logError(any:Dynamic, ?pos:PosInfos):Void {//TODO: limit access via @:allow
|
||||
|
||||
log('Error: $any', pos);
|
||||
}
|
||||
|
||||
/** used internally, calls log error if the condition is false. EX: if (assert(data != null, "null data")) */
|
||||
inline public function assert(condition:Bool, msg:Dynamic, ?pos:PosInfos):Bool {//TODO: limit access via @:allow
|
||||
if (!condition)
|
||||
logError(msg, pos);
|
||||
|
||||
return condition;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// ENCRYPTION
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
/** Sets */
|
||||
public function initEncryption
|
||||
( key :String
|
||||
, cipher:Cipher = Cipher.RC4
|
||||
, format:EncryptionFormat = EncryptionFormat.BASE_64
|
||||
):Void {
|
||||
|
||||
if (cipher == Cipher.NONE)
|
||||
encryptionHandler = null;
|
||||
else if (cipher == Cipher.RC4)
|
||||
encryptionHandler = encryptRc4.bind(key, format);
|
||||
else
|
||||
throw "aes not yet implemented";
|
||||
}
|
||||
|
||||
function encryptRc4(key:String, format:EncryptionFormat, data:String):String {
|
||||
|
||||
if (format == EncryptionFormat.HEX)
|
||||
throw "hex format not yet implemented";
|
||||
|
||||
var keyBytes:Bytes;
|
||||
if (format == EncryptionFormat.BASE_64)
|
||||
keyBytes = Base64.decode(key);
|
||||
else
|
||||
keyBytes = null;//TODO
|
||||
|
||||
var dataBytes = new Rc4(keyBytes).crypt(Bytes.ofString(data));
|
||||
|
||||
if (format == EncryptionFormat.BASE_64)
|
||||
return Base64.encode(dataBytes);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package io.newgrounds.components;
|
||||
|
||||
import io.newgrounds.objects.events.Result;
|
||||
import io.newgrounds.objects.events.Result.SessionResult;
|
||||
import io.newgrounds.NGLite;
|
||||
|
||||
class AppComponent extends Component {
|
||||
|
||||
public function new (core:NGLite) { super(core); }
|
||||
|
||||
public function startSession(force:Bool = false):Call<SessionResult> {
|
||||
|
||||
return new Call<SessionResult>(_core, "App.startSession")
|
||||
.addComponentParameter("force", force, false);
|
||||
}
|
||||
|
||||
public function checkSession():Call<SessionResult> {
|
||||
|
||||
return new Call<SessionResult>(_core, "App.checkSession", true);
|
||||
}
|
||||
|
||||
public function endSession():Call<SessionResult> {
|
||||
|
||||
return new Call<SessionResult>(_core, "App.endSession", true);
|
||||
}
|
||||
|
||||
public function getCurrentVersion(version:String):Call<GetCurrentVersionResult> {
|
||||
|
||||
return new Call<GetCurrentVersionResult>(_core, "App.getCurrentVersion")
|
||||
.addComponentParameter("version", version);
|
||||
}
|
||||
|
||||
public function getHostLicense():Call<GetHostResult> {
|
||||
|
||||
return new Call<GetHostResult>(_core, "App.getHostLicense")
|
||||
.addComponentParameter("host", _core.host);
|
||||
}
|
||||
|
||||
public function logView():Call<ResultBase> {
|
||||
|
||||
return new Call<ResultBase>(_core, "App.logView")
|
||||
.addComponentParameter("host", _core.host);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package io.newgrounds.components;
|
||||
|
||||
import io.newgrounds.NGLite;
|
||||
|
||||
class Component {
|
||||
|
||||
var _core:NGLite;
|
||||
|
||||
public function new(core:NGLite) {
|
||||
|
||||
this._core = core;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package io.newgrounds.components;
|
||||
class ComponentList {
|
||||
|
||||
var _core:NGLite;
|
||||
|
||||
// --- COMPONENTS
|
||||
public var medal : MedalComponent;
|
||||
public var app : AppComponent;
|
||||
public var event : EventComponent;
|
||||
public var scoreBoard: ScoreBoardComponent;
|
||||
public var loader : LoaderComponent;
|
||||
public var gateway : GatewayComponent;
|
||||
|
||||
public function new(core:NGLite) {
|
||||
|
||||
_core = core;
|
||||
|
||||
medal = new MedalComponent (_core);
|
||||
app = new AppComponent (_core);
|
||||
event = new EventComponent (_core);
|
||||
scoreBoard = new ScoreBoardComponent(_core);
|
||||
loader = new LoaderComponent (_core);
|
||||
gateway = new GatewayComponent (_core);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package io.newgrounds.components;
|
||||
|
||||
import io.newgrounds.objects.events.Result.LogEventResult;
|
||||
import io.newgrounds.NGLite;
|
||||
|
||||
class EventComponent extends Component {
|
||||
|
||||
public function new (core:NGLite){ super(core); }
|
||||
|
||||
public function logEvent(eventName:String):Call<LogEventResult> {
|
||||
|
||||
return new Call<LogEventResult>(_core, "Event.logEvent")
|
||||
.addComponentParameter("event_name", eventName)
|
||||
.addComponentParameter("host", _core.host);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package io.newgrounds.components;
|
||||
|
||||
import io.newgrounds.objects.events.Result;
|
||||
import io.newgrounds.NGLite;
|
||||
|
||||
class GatewayComponent extends Component {
|
||||
|
||||
public function new (core:NGLite){ super(core); }
|
||||
|
||||
public function getDatetime():Call<GetDateTimeResult> {
|
||||
|
||||
return new Call<GetDateTimeResult>(_core, "Gateway.getDatetime");
|
||||
}
|
||||
|
||||
public function getVersion():Call<GetVersionResult> {
|
||||
|
||||
return new Call<GetVersionResult>(_core, "Gateway.getVersion");
|
||||
}
|
||||
|
||||
public function ping():Call<PingResult> {
|
||||
|
||||
return new Call<PingResult>(_core, "Gateway.ping");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package io.newgrounds.components;
|
||||
|
||||
import io.newgrounds.objects.events.Result;
|
||||
import io.newgrounds.NGLite;
|
||||
|
||||
class LoaderComponent extends Component {
|
||||
|
||||
public function new (core:NGLite){ super(core); }
|
||||
|
||||
public function loadAuthorUrl(redirect:Bool = false):Call<ResultBase> {
|
||||
|
||||
return new Call<ResultBase>(_core, "Loader.loadAuthorUrl")
|
||||
.addComponentParameter("host", _core.host)
|
||||
.addComponentParameter("redirect", redirect, true);
|
||||
}
|
||||
|
||||
public function loadMoreGames(redirect:Bool = false):Call<ResultBase> {
|
||||
|
||||
return new Call<ResultBase>(_core, "Loader.loadMoreGames")
|
||||
.addComponentParameter("host", _core.host)
|
||||
.addComponentParameter("redirect", redirect, true);
|
||||
}
|
||||
|
||||
public function loadNewgrounds(redirect:Bool = false):Call<ResultBase> {
|
||||
|
||||
return new Call<ResultBase>(_core, "Loader.loadNewgrounds")
|
||||
.addComponentParameter("host", _core.host)
|
||||
.addComponentParameter("redirect", redirect, true);
|
||||
}
|
||||
|
||||
public function loadOfficialUrl(redirect:Bool = false):Call<ResultBase> {
|
||||
|
||||
return new Call<ResultBase>(_core, "Loader.loadOfficialUrl")
|
||||
.addComponentParameter("host", _core.host)
|
||||
.addComponentParameter("redirect", redirect, true);
|
||||
}
|
||||
|
||||
public function loadReferral(redirect:Bool = false):Call<ResultBase> {
|
||||
|
||||
return new Call<ResultBase>(_core, "Loader.loadReferral")
|
||||
.addComponentParameter("host", _core.host)
|
||||
.addComponentParameter("redirect", redirect, true);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package io.newgrounds.components;
|
||||
|
||||
import io.newgrounds.objects.events.Result;
|
||||
import io.newgrounds.Call;
|
||||
import io.newgrounds.NGLite;
|
||||
|
||||
class MedalComponent extends Component {
|
||||
|
||||
public function new(core:NGLite):Void { super(core); }
|
||||
|
||||
public function unlock(id:Int):Call<MedalUnlockResult> {
|
||||
|
||||
return new Call<MedalUnlockResult>(_core, "Medal.unlock", true, true)
|
||||
.addComponentParameter("id", id);
|
||||
}
|
||||
|
||||
public function getList():Call<MedalListResult> {
|
||||
|
||||
return new Call<MedalListResult>(_core, "Medal.getList");
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
package io.newgrounds.components;
|
||||
|
||||
import io.newgrounds.objects.User;
|
||||
import io.newgrounds.objects.events.Response;
|
||||
import io.newgrounds.objects.events.Result;
|
||||
import io.newgrounds.objects.events.Result.ScoreBoardResult;
|
||||
import io.newgrounds.objects.events.Result.ScoreResult;
|
||||
import io.newgrounds.NGLite;
|
||||
import io.newgrounds.objects.ScoreBoard;
|
||||
|
||||
import haxe.ds.IntMap;
|
||||
|
||||
class ScoreBoardComponent extends Component {
|
||||
|
||||
public var allById:IntMap<ScoreBoard>;
|
||||
|
||||
public function new (core:NGLite){ super(core); }
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// GET SCORES
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
public function getBoards():Call<ScoreBoardResult> {
|
||||
|
||||
return new Call<ScoreBoardResult>(_core, "ScoreBoard.getBoards");
|
||||
}
|
||||
|
||||
/*function onBoardsReceive(response:Response<ScoreBoardResult>):Void {
|
||||
|
||||
if (!response.result.success)
|
||||
return;
|
||||
|
||||
allById = new IntMap<ScoreBoard>();
|
||||
|
||||
for (boardData in response.result.scoreboards)
|
||||
createBoard(boardData);
|
||||
|
||||
_core.log('${response.result.scoreboards.length} ScoreBoards loaded');
|
||||
}*/
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// GET SCORES
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
public function getScores
|
||||
( id :Int
|
||||
, limit :Int = 10
|
||||
, skip :Int = 0
|
||||
, period:Period = Period.DAY
|
||||
, social:Bool = false
|
||||
, tag :String = null
|
||||
, user :Dynamic = null
|
||||
):Call<ScoreResult> {
|
||||
|
||||
if (user != null && !Std.is(user, String) && !Std.is(user, Int))
|
||||
user = user.id;
|
||||
|
||||
return new Call<ScoreResult>(_core, "ScoreBoard.getScores")
|
||||
.addComponentParameter("id" , id )
|
||||
.addComponentParameter("limit" , limit , 10)
|
||||
.addComponentParameter("skip" , skip , 0)
|
||||
.addComponentParameter("period", period, Period.DAY)
|
||||
.addComponentParameter("social", social, false)
|
||||
.addComponentParameter("tag" , tag , null)
|
||||
.addComponentParameter("user" , user , null);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// POST SCORE
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
public function postScore(id:Int, value:Int, tag:String = null):Call<PostScoreResult> {
|
||||
|
||||
return new Call<PostScoreResult>(_core, "ScoreBoard.postScore", true, true)
|
||||
.addComponentParameter("id" , id)
|
||||
.addComponentParameter("value", value)
|
||||
.addComponentParameter("tag" , tag , null);
|
||||
}
|
||||
|
||||
/*function onScorePosted(response:Response<ResultBase>):Void {
|
||||
|
||||
if (!response.result.success)
|
||||
return;
|
||||
|
||||
allById = new IntMap<ScoreBoard>();
|
||||
|
||||
//createBoard(data.data.scoreBoard).parseScores(data.data.scores);
|
||||
}*/
|
||||
|
||||
inline function createBoard(data:Dynamic):ScoreBoard {
|
||||
|
||||
var board = new ScoreBoard(_core, data);
|
||||
_core.logVerbose('created $board');
|
||||
|
||||
allById.set(board.id, board);
|
||||
|
||||
return board;
|
||||
}
|
||||
}
|
||||
|
||||
@:enum
|
||||
abstract Period(String) to String from String{
|
||||
|
||||
/** Indicates scores are from the current day. */
|
||||
var DAY = "D";
|
||||
/** Indicates scores are from the current week. */
|
||||
var WEEK = "W";
|
||||
/** Indicates scores are from the current month. */
|
||||
var MONTH = "M";
|
||||
/** Indicates scores are from the current year. */
|
||||
var YEAR = "Y";
|
||||
/** Indicates scores are from all-time. */
|
||||
var ALL = "A";
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package io.newgrounds.crypto;
|
||||
|
||||
@:enum
|
||||
abstract Cipher(String) to String{
|
||||
var NONE = "none";
|
||||
var AES_128 = "aes128";
|
||||
var RC4 = "rc4";
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package io.newgrounds.crypto;
|
||||
|
||||
@:enum
|
||||
abstract EncryptionFormat(String) to String {
|
||||
var BASE_64 = "base64";
|
||||
var HEX = "hex";
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package io.newgrounds.crypto;
|
||||
|
||||
import haxe.io.Bytes;
|
||||
|
||||
/**
|
||||
* The following was straight-up ganked from https://github.com/iskolbin/rc4hx
|
||||
*
|
||||
* You da real MVP iskolbin...
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 iskolbin
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
**/
|
||||
class Rc4 {
|
||||
var perm = Bytes.alloc( 256 );
|
||||
var index1: Int = 0;
|
||||
var index2: Int = 0;
|
||||
|
||||
public function new( key: Bytes ) {
|
||||
for ( i in 0...256 ) {
|
||||
perm.set( i, i );
|
||||
}
|
||||
|
||||
var j: Int = 0;
|
||||
for ( i in 0...256 ) {
|
||||
j = ( j + perm.get( i ) + key.get( i % key.length )) % 256;
|
||||
swap( i, j );
|
||||
}
|
||||
}
|
||||
|
||||
inline function swap( i: Int, j: Int ): Void {
|
||||
var temp = perm.get( i );
|
||||
perm.set( i, perm.get( j ));
|
||||
perm.set( j, temp );
|
||||
}
|
||||
|
||||
public function crypt( input: Bytes ): Bytes {
|
||||
var output = Bytes.alloc( input.length );
|
||||
|
||||
for ( i in 0...input.length ) {
|
||||
index1 = ( index1 + 1 ) % 256;
|
||||
index2 = ( index2 + perm.get( index1 )) % 256;
|
||||
swap( index1, index2 );
|
||||
var j = ( perm.get( index1 ) + perm.get( index2 )) % 256;
|
||||
output.set( i, input.get( i ) ^ perm.get( j ));
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package io.newgrounds.objects;
|
||||
class Error {
|
||||
|
||||
public var code(default, null):Int;
|
||||
public var message(default, null):String;
|
||||
|
||||
public function new (message:String, code:Int = 0) {
|
||||
|
||||
this.message = message;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public function toString():String {
|
||||
|
||||
if (code > 0)
|
||||
return '#$code - $message';
|
||||
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
package io.newgrounds.objects;
|
||||
|
||||
import io.newgrounds.objects.events.Response;
|
||||
import io.newgrounds.objects.events.Result.MedalUnlockResult;
|
||||
import io.newgrounds.utils.Dispatcher;
|
||||
import io.newgrounds.NGLite;
|
||||
|
||||
class Medal extends Object {
|
||||
|
||||
inline static public var EASY :Int = 1;
|
||||
inline static public var MODERATE :Int = 2;
|
||||
inline static public var CHALLENGING:Int = 3;
|
||||
inline static public var DIFFICULT :Int = 4;
|
||||
inline static public var BRUTAL :Int = 5;
|
||||
|
||||
static var difficultyNames:Array<String> =
|
||||
[ "Easy"
|
||||
, "Moderate"
|
||||
, "Challenging"
|
||||
, "Difficult"
|
||||
, "Brutal"
|
||||
];
|
||||
// --- FROM SERVER
|
||||
public var id (default, null):Int;
|
||||
public var name (default, null):String;
|
||||
public var description(default, null):String;
|
||||
public var icon (default, null):String;
|
||||
public var value (default, null):Int;
|
||||
public var difficulty (default, null):Int;
|
||||
public var secret (default, null):Bool;
|
||||
public var unlocked (default, null):Bool;
|
||||
// --- HELPERS
|
||||
public var difficultyName(get, never):String;
|
||||
|
||||
public var onUnlock:Dispatcher;
|
||||
|
||||
public function new(core:NGLite, data:Dynamic = null):Void {
|
||||
|
||||
onUnlock = new Dispatcher();
|
||||
|
||||
super(core, data);
|
||||
}
|
||||
|
||||
@:allow(io.newgrounds.NG)
|
||||
override function parse(data:Dynamic):Void {
|
||||
|
||||
var wasLocked = !unlocked;
|
||||
|
||||
id = data.id;
|
||||
name = data.name;
|
||||
description = data.description;
|
||||
icon = data.icon;
|
||||
value = data.value;
|
||||
difficulty = data.difficulty;
|
||||
secret = data.secret == 1;
|
||||
unlocked = data.unlocked;
|
||||
|
||||
super.parse(data);
|
||||
|
||||
if (wasLocked && unlocked)
|
||||
onUnlock.dispatch();
|
||||
|
||||
}
|
||||
|
||||
public function sendUnlock():Void {
|
||||
|
||||
if (_core.sessionId == null) {
|
||||
// --- Unlock regardless, show medal popup to encourage NG signup
|
||||
unlocked = true;
|
||||
onUnlock.dispatch();
|
||||
//TODO: save unlock in local save
|
||||
}
|
||||
|
||||
_core.calls.medal.unlock(id)
|
||||
.addDataHandler(onUnlockResponse)
|
||||
.send();
|
||||
}
|
||||
|
||||
function onUnlockResponse(response:Response<MedalUnlockResult>):Void {
|
||||
|
||||
if (response.success && response.result.success) {
|
||||
|
||||
parse(response.result.data.medal);
|
||||
|
||||
// --- Unlock response doesn't include unlock=true, so parse won't change it.
|
||||
if (!unlocked) {
|
||||
|
||||
unlocked = true;
|
||||
onUnlock.dispatch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Locks the medal on the client and sends an unlock request, Server responds the same either way. */
|
||||
public function sendDebugUnlock():Void {
|
||||
|
||||
if (NG.core.sessionId == null) {
|
||||
|
||||
onUnlock.dispatch();
|
||||
|
||||
} else {
|
||||
|
||||
unlocked = false;
|
||||
|
||||
sendUnlock();
|
||||
}
|
||||
}
|
||||
|
||||
public function get_difficultyName():String {
|
||||
|
||||
return difficultyNames[difficulty - 1];
|
||||
}
|
||||
|
||||
public function toString():String {
|
||||
|
||||
return 'Medal: $id@$name (${unlocked ? "unlocked" : "locked"}, $value pts, $difficultyName).';
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package io.newgrounds.objects;
|
||||
|
||||
import io.newgrounds.utils.Dispatcher;
|
||||
import io.newgrounds.NGLite;
|
||||
|
||||
class Object {
|
||||
|
||||
var _core:NGLite;
|
||||
|
||||
public var onUpdate(default, null):Dispatcher;
|
||||
|
||||
public function new(core:NGLite, data:Dynamic = null) {
|
||||
|
||||
this._core = core;
|
||||
|
||||
onUpdate = new Dispatcher();
|
||||
|
||||
if (data != null)
|
||||
parse(data);
|
||||
}
|
||||
|
||||
@:allow(io.newgrounds.NGLite)
|
||||
function parse(data:Dynamic):Void {
|
||||
|
||||
onUpdate.dispatch();
|
||||
}
|
||||
|
||||
|
||||
public function destroy():Void {
|
||||
|
||||
_core = null;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package io.newgrounds.objects;
|
||||
|
||||
/** We don't want to serialize scores since there's a bajillion of them. */
|
||||
typedef Score = {
|
||||
|
||||
/** The value value in the format selected in your scoreboard settings. */
|
||||
var formatted_value:String;
|
||||
|
||||
/** The tag attached to this value (if any). */
|
||||
var tag:String;
|
||||
|
||||
/** The user who earned value. If this property is absent, the value belongs to the active user. */
|
||||
var user:User;
|
||||
|
||||
/** The integer value of the value. */
|
||||
var value:Int;
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package io.newgrounds.objects;
|
||||
|
||||
import io.newgrounds.components.ScoreBoardComponent.Period;
|
||||
import io.newgrounds.objects.events.Response;
|
||||
import io.newgrounds.objects.events.Result;
|
||||
import io.newgrounds.objects.events.Result.ScoreResult;
|
||||
import io.newgrounds.NGLite;
|
||||
|
||||
class ScoreBoard extends Object {
|
||||
|
||||
public var scores(default, null):Array<Score>;
|
||||
|
||||
/** The numeric ID of the scoreboard.*/
|
||||
public var id(default, null):Int;
|
||||
|
||||
/** The name of the scoreboard. */
|
||||
public var name(default, null):String;
|
||||
|
||||
public function new(core:NGLite, data:Dynamic):Void {super(core, data); }
|
||||
|
||||
override function parse(data:Dynamic):Void {
|
||||
|
||||
id = data.id;
|
||||
name = data.name;
|
||||
|
||||
super.parse(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches score data from the server, this removes all of the existing scores cached
|
||||
*
|
||||
* We don't unify the old and new scores because a user's rank or score may change between requests
|
||||
*/
|
||||
public function requestScores
|
||||
( limit :Int = 10
|
||||
, skip :Int = 0
|
||||
, period:Period = Period.ALL
|
||||
, social:Bool = false
|
||||
, tag :String = null
|
||||
, user :Dynamic = null
|
||||
):Void {
|
||||
|
||||
_core.calls.scoreBoard.getScores(id, limit, skip, period, social, tag, user)
|
||||
.addDataHandler(onScoresReceived)
|
||||
.send();
|
||||
}
|
||||
|
||||
function onScoresReceived(response:Response<ScoreResult>):Void {
|
||||
|
||||
if (!response.success || !response.result.success)
|
||||
return;
|
||||
|
||||
scores = response.result.data.scores;
|
||||
_core.logVerbose('received ${scores.length} scores');
|
||||
|
||||
onUpdate.dispatch();
|
||||
}
|
||||
|
||||
public function postScore(value :Int, tag:String = null):Void {
|
||||
|
||||
_core.calls.scoreBoard.postScore(id, value, tag)
|
||||
.addDataHandler(onScorePosted)
|
||||
.send();
|
||||
}
|
||||
|
||||
function onScorePosted(response:Response<PostScoreResult>):Void {
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function toString():String {
|
||||
|
||||
return 'ScoreBoard: $id@$name';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package io.newgrounds.objects;
|
||||
|
||||
class Session extends Object {
|
||||
|
||||
/** If true, the session_id is expired. Use App.startSession to get a new one.*/
|
||||
public var expired(default, null):Bool;
|
||||
|
||||
/** A unique session identifier */
|
||||
public var id(default, null):String;
|
||||
|
||||
/** If the session has no associated user but is not expired, this property will provide a URL that can be used to sign the user in. */
|
||||
public var passportUrl(default, null):String;
|
||||
|
||||
/** If true, the user would like you to remember their session id. */
|
||||
public var remember(default, null):Bool;
|
||||
|
||||
/** If the user has not signed in, or granted access to your app, this will be null */
|
||||
public var user(default, null):User;
|
||||
|
||||
//TODO:desciption
|
||||
public var status(get, never):SessionStatus;
|
||||
|
||||
public function new(core:NGLite, data:Dynamic = null) { super(core, data); }
|
||||
|
||||
override public function parse(data:Dynamic):Void {
|
||||
|
||||
id = data.id;
|
||||
expired = data.expired;
|
||||
passportUrl = data.passport_url;
|
||||
remember = data.remember;
|
||||
|
||||
// --- KEEP THE SAME INSTANCE
|
||||
if (user == null)
|
||||
user = data.user;
|
||||
// TODO?: update original user instance with new data. (probly not)
|
||||
|
||||
super.parse(data);
|
||||
}
|
||||
|
||||
public function get_status():SessionStatus {
|
||||
|
||||
if (expired || id == null || id == "")
|
||||
return SessionStatus.SESSION_EXPIRED;
|
||||
|
||||
if (user != null && user.name != null && user.name != "")
|
||||
return SessionStatus.USER_LOADED;
|
||||
|
||||
return SessionStatus.REQUEST_LOGIN;
|
||||
}
|
||||
|
||||
public function expire():Void {
|
||||
|
||||
expired = true;
|
||||
id = null;
|
||||
user = null;
|
||||
}
|
||||
}
|
||||
|
||||
@:enum
|
||||
abstract SessionStatus(String) {
|
||||
|
||||
var SESSION_EXPIRED = "session-expired";
|
||||
var REQUEST_LOGIN = "request-login";
|
||||
var USER_LOADED = "user-loaded";
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package io.newgrounds.objects;
|
||||
|
||||
typedef User = {
|
||||
|
||||
/** The user's icon images. */
|
||||
var icons:UserIcons;
|
||||
|
||||
/** The user's numeric ID. */
|
||||
var id:Int;
|
||||
|
||||
/** The user's textual name. */
|
||||
var name:String;
|
||||
|
||||
/** Returns true if the user has a Newgrounds Supporter upgrade. */
|
||||
var supporter:Bool;
|
||||
|
||||
/** The user's NG profile url. */
|
||||
var url:String;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package io.newgrounds.objects;
|
||||
|
||||
typedef UserIcons = {
|
||||
|
||||
/**The URL of the user's large icon. */
|
||||
var large:String;
|
||||
|
||||
/** The URL of the user's medium icon. */
|
||||
var medium:String;
|
||||
|
||||
/** The URL of the user's small icon. */
|
||||
var small:String;
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
package io.newgrounds.objects.events;
|
||||
|
||||
import io.newgrounds.objects.events.Result.ResultBase;
|
||||
import haxe.Json;
|
||||
import io.newgrounds.objects.Error;
|
||||
|
||||
typedef DebugResponse = {
|
||||
|
||||
var exec_time:Int;
|
||||
var input:Dynamic;
|
||||
}
|
||||
|
||||
class Response<T:ResultBase> {
|
||||
|
||||
public var success(default, null):Bool;
|
||||
public var error(default, null):Error;
|
||||
public var debug(default, null):DebugResponse;
|
||||
public var result(default, null):Result<T>;
|
||||
|
||||
public function new (core:NGLite, reply:String) {
|
||||
|
||||
var data:Dynamic;
|
||||
|
||||
try {
|
||||
data = Json.parse(reply);
|
||||
|
||||
} catch (e:Dynamic) {
|
||||
|
||||
data = Json.parse('{"success":false,"error":{"message":"${Std.string(reply)}","code":0}}');
|
||||
}
|
||||
|
||||
success = data.success;
|
||||
debug = data.debug;
|
||||
|
||||
if (!success) {
|
||||
error = new Error(data.error.message, data.error.code);
|
||||
core.logError('Call unseccessful: $error');
|
||||
return;
|
||||
}
|
||||
|
||||
result = new Result<T>(core, data.result);
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
package io.newgrounds.objects.events;
|
||||
|
||||
class Result<T:ResultBase> {
|
||||
|
||||
public var echo(default, null):String;
|
||||
public var component(default, null):String;
|
||||
|
||||
public var data(default, null):T;
|
||||
public var success(default, null):Bool;
|
||||
public var debug(default, null):Bool;
|
||||
public var error(default, null):Error;
|
||||
|
||||
public function new(core:NGLite, data:Dynamic) {
|
||||
|
||||
echo = data.echo;
|
||||
component = data.component;
|
||||
|
||||
data = data.data;
|
||||
success = data.success;
|
||||
debug = data.debug;
|
||||
|
||||
if(!data.success) {
|
||||
|
||||
error = new Error(data.error.message, data.error.code);
|
||||
core.logError('$component fail: $error');
|
||||
|
||||
} else
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
typedef ResultBase = { };
|
||||
|
||||
typedef SessionResult = {
|
||||
> ResultBase,
|
||||
|
||||
var session:Dynamic;
|
||||
}
|
||||
|
||||
typedef GetHostResult = {
|
||||
> ResultBase,
|
||||
|
||||
var host_approved:Bool;
|
||||
}
|
||||
|
||||
typedef GetCurrentVersionResult = {
|
||||
> ResultBase,
|
||||
|
||||
var current_version:String;
|
||||
var client_deprecated:Bool;
|
||||
}
|
||||
|
||||
typedef LogEventResult = {
|
||||
> ResultBase,
|
||||
|
||||
var event_name:String;
|
||||
}
|
||||
|
||||
typedef GetDateTimeResult = {
|
||||
> ResultBase,
|
||||
|
||||
var datetime:String;
|
||||
}
|
||||
|
||||
typedef GetVersionResult = {
|
||||
> ResultBase,
|
||||
|
||||
var version:String;
|
||||
}
|
||||
|
||||
typedef PingResult = {
|
||||
> ResultBase,
|
||||
|
||||
var pong:String;
|
||||
}
|
||||
|
||||
typedef MedalListResult = {
|
||||
> ResultBase,
|
||||
|
||||
var medals:Array<Dynamic>;
|
||||
}
|
||||
|
||||
typedef MedalUnlockResult = {
|
||||
> ResultBase,
|
||||
|
||||
var medal_score:String;
|
||||
var medal:Dynamic;
|
||||
}
|
||||
|
||||
typedef ScoreBoardResult = {
|
||||
> ResultBase,
|
||||
|
||||
var scoreboards:Array<Dynamic>;
|
||||
}
|
||||
|
||||
typedef ScoreResult = {
|
||||
> ResultBase,
|
||||
|
||||
var scores:Array<Score>;
|
||||
var scoreboard:Dynamic;
|
||||
}
|
||||
|
||||
typedef PostScoreResult = {
|
||||
> ResultBase,
|
||||
|
||||
var tag:String;
|
||||
var scoreboard:Dynamic;
|
||||
var score:Score;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package io.newgrounds.swf;
|
||||
|
||||
import openfl.display.MovieClip;
|
||||
|
||||
class LoadingBar extends MovieClip {
|
||||
|
||||
public var bar(default, null):MovieClip;
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
|
||||
setProgress(0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param value The ratio of bytes loaded to bytes total
|
||||
*/
|
||||
public function setProgress(value:Float):Void {
|
||||
|
||||
bar.gotoAndStop(1 + Std.int(value * (bar.totalFrames - 1)));
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
package io.newgrounds.swf;
|
||||
|
||||
import io.newgrounds.swf.common.BaseAsset;
|
||||
import io.newgrounds.objects.Medal;
|
||||
|
||||
import openfl.text.TextFieldAutoSize;
|
||||
import openfl.text.TextField;
|
||||
import openfl.display.DisplayObject;
|
||||
import openfl.display.Loader;
|
||||
import openfl.display.MovieClip;
|
||||
import openfl.net.URLRequest;
|
||||
import openfl.events.Event;
|
||||
|
||||
class MedalPopup extends BaseAsset {
|
||||
|
||||
static inline var FRAME_HIDDEN:String = "hidden";
|
||||
static inline var FRAME_MEDAL_UNLOCKED:String = "medalUnlocked";
|
||||
static inline var FRAME_INTRO_COMPLETE:String = "introComplete";
|
||||
static inline var FRAME_UNLOCK_COMPLETE:String = "unlockComplete";
|
||||
static inline var MIN_TEXT_SIZE:Int = 12;
|
||||
|
||||
public var medalIcon(default, null):MovieClip;
|
||||
public var medalName(default, null):MovieClip;
|
||||
public var medalPoints(default, null):MovieClip;
|
||||
|
||||
public var alwaysOnTop:Bool;
|
||||
#if !ng_lite
|
||||
public var requiresSession:Bool;
|
||||
#end
|
||||
|
||||
var _animQueue = new Array<Void->Void>();
|
||||
var _scrollSpeed:Float;
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
|
||||
mouseEnabled = false;
|
||||
mouseChildren = false;
|
||||
|
||||
hide();
|
||||
addFrameScript(totalFrames - 1, onUnlockAnimComplete);
|
||||
}
|
||||
|
||||
function hide():Void {
|
||||
|
||||
visible = false;
|
||||
gotoAndStop(FRAME_HIDDEN);
|
||||
}
|
||||
|
||||
#if !ng_lite
|
||||
override function onReady():Void {
|
||||
super.onReady();
|
||||
|
||||
if (NG.core.medals != null)
|
||||
onMedalsLoaded();
|
||||
else
|
||||
NG.core.onLogin.addOnce(NG.core.requestMedals.bind(onMedalsLoaded));
|
||||
}
|
||||
|
||||
function onMedalsLoaded():Void {
|
||||
|
||||
for (medal in NG.core.medals)
|
||||
medal.onUnlock.add(onMedalOnlock.bind(medal));
|
||||
}
|
||||
|
||||
function onMedalOnlock(medal:Medal):Void {
|
||||
|
||||
if (requiresSession && !NG.core.loggedIn)
|
||||
return;
|
||||
|
||||
var loader = new Loader();
|
||||
loader.load(new URLRequest(medal.icon));
|
||||
|
||||
playAnim(loader, medal.name, medal.value);
|
||||
}
|
||||
|
||||
#end
|
||||
|
||||
public function playAnim(icon:DisplayObject, name:String, value:Int):Void {
|
||||
|
||||
if (currentLabel == FRAME_HIDDEN)
|
||||
playNextAnim(icon, name, value);
|
||||
else
|
||||
_animQueue.push(playNextAnim.bind(icon, name, value));
|
||||
}
|
||||
|
||||
function playNextAnim(icon:DisplayObject, name:String, value:Int):Void {
|
||||
|
||||
visible = true;
|
||||
gotoAndPlay(FRAME_MEDAL_UNLOCKED);
|
||||
|
||||
if (alwaysOnTop && parent != null) {
|
||||
|
||||
parent.setChildIndex(this, parent.numChildren - 1);
|
||||
}
|
||||
|
||||
while(medalIcon.numChildren > 0)
|
||||
medalIcon.removeChildAt(0);
|
||||
|
||||
cast(medalPoints.getChildByName("field"), TextField).text = Std.string(value);
|
||||
|
||||
var field:TextField = cast medalName.getChildByName("field");
|
||||
field.autoSize = TextFieldAutoSize.LEFT;
|
||||
field.x = 0;
|
||||
field.text = "";
|
||||
var oldWidth = medalName.width;
|
||||
field.text = name;
|
||||
|
||||
_scrollSpeed = 0;
|
||||
if (field.width > oldWidth + 4) {
|
||||
|
||||
field.x = oldWidth + 4;
|
||||
initScroll(field);
|
||||
}
|
||||
|
||||
medalIcon.addChild(icon);
|
||||
}
|
||||
|
||||
function initScroll(field:TextField):Void {
|
||||
//TODO: Find out why scrollrect didn't work
|
||||
|
||||
var animDuration = 0;
|
||||
|
||||
for (frame in currentLabels){
|
||||
|
||||
if (frame.name == FRAME_INTRO_COMPLETE )
|
||||
animDuration -= frame.frame;
|
||||
else if (frame.name == FRAME_UNLOCK_COMPLETE)
|
||||
animDuration += frame.frame;
|
||||
}
|
||||
|
||||
_scrollSpeed = (field.width + field.x + 4) / animDuration;
|
||||
field.addEventListener(Event.ENTER_FRAME, updateScroll);
|
||||
}
|
||||
|
||||
function updateScroll(e:Event):Void{
|
||||
|
||||
if (currentLabel == FRAME_INTRO_COMPLETE)
|
||||
cast (e.currentTarget, TextField).x -= _scrollSpeed;
|
||||
}
|
||||
|
||||
function onUnlockAnimComplete():Void {
|
||||
|
||||
cast (medalName.getChildByName("field"), TextField).removeEventListener(Event.ENTER_FRAME, updateScroll);
|
||||
|
||||
if (_animQueue.length == 0)
|
||||
hide();
|
||||
else
|
||||
(_animQueue.shift())();
|
||||
}
|
||||
}
|
||||
@@ -1,250 +0,0 @@
|
||||
package io.newgrounds.swf;
|
||||
|
||||
import openfl.events.Event;
|
||||
import io.newgrounds.swf.common.DropDown;
|
||||
import io.newgrounds.objects.Score;
|
||||
import io.newgrounds.objects.events.Result.ScoreBoardResult;
|
||||
import io.newgrounds.objects.events.Result.ScoreResult;
|
||||
import io.newgrounds.objects.events.Response;
|
||||
import io.newgrounds.swf.common.BaseAsset;
|
||||
import io.newgrounds.swf.common.Button;
|
||||
import io.newgrounds.components.ScoreBoardComponent.Period;
|
||||
|
||||
import openfl.display.MovieClip;
|
||||
import openfl.text.TextField;
|
||||
|
||||
class ScoreBrowser extends BaseAsset {
|
||||
|
||||
public var prevButton (default, null):MovieClip;
|
||||
public var nextButton (default, null):MovieClip;
|
||||
public var reloadButton (default, null):MovieClip;
|
||||
public var listBox (default, null):MovieClip;
|
||||
public var loadingIcon (default, null):MovieClip;
|
||||
public var errorIcon (default, null):MovieClip;
|
||||
public var scoreContainer(default, null):MovieClip;
|
||||
public var titleField (default, null):TextField;
|
||||
public var pageField (default, null):TextField;
|
||||
|
||||
public var period(get, set):Period;
|
||||
function get_period():Period { return _periodDropDown.value; }
|
||||
function set_period(value:Period):Period { return _periodDropDown.value = value; }
|
||||
|
||||
public var title(get, set):String;
|
||||
function get_title():String { return titleField.text; }
|
||||
function set_title(value:String):String { return titleField.text = value; }
|
||||
|
||||
public var tag(default, set):String;
|
||||
function set_tag(value:String):String {
|
||||
|
||||
if (this.tag != value) {
|
||||
|
||||
this.tag = value;
|
||||
delayReload();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public var social(default, set):Bool;
|
||||
function set_social(value:Bool):Bool {
|
||||
|
||||
if (this.social != value) {
|
||||
|
||||
this.social = value;
|
||||
delayReload();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public var boardId(default, set):Int;
|
||||
function set_boardId(value:Int):Int {
|
||||
|
||||
_boardIDSet = true;
|
||||
|
||||
if (this.boardId != value) {
|
||||
|
||||
this.boardId = value;
|
||||
delayReload();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public var page(default, set):Int;
|
||||
function set_page(value:Int):Int {
|
||||
|
||||
if (this.page != value) {
|
||||
|
||||
this.page = value;
|
||||
delayReload();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
var _scores:Array<MovieClip>;
|
||||
var _limit:Int = 0;
|
||||
var _periodDropDown:DropDown;
|
||||
var _boardIDSet:Bool;
|
||||
|
||||
public function new() { super(); }
|
||||
|
||||
override function setDefaults():Void {
|
||||
super.setDefaults();
|
||||
|
||||
boardId = -1;
|
||||
_boardIDSet = false;
|
||||
|
||||
scoreContainer.visible = false;
|
||||
loadingIcon.visible = false;
|
||||
reloadButton.visible = false;
|
||||
errorIcon.visible = false;
|
||||
errorIcon.addFrameScript(errorIcon.totalFrames - 1, errorIcon.stop);
|
||||
|
||||
//TODO: prevent memory leaks?
|
||||
new Button(prevButton, onPrevClick);
|
||||
new Button(nextButton, onNextClick);
|
||||
new Button(reloadButton, reload);
|
||||
_periodDropDown = new DropDown(listBox, delayReload);
|
||||
_periodDropDown.addItem("Current day" , Period.DAY );
|
||||
_periodDropDown.addItem("Current week" , Period.WEEK );
|
||||
_periodDropDown.addItem("Current month", Period.MONTH);
|
||||
_periodDropDown.addItem("Current year" , Period.YEAR );
|
||||
_periodDropDown.addItem("All time" , Period.ALL );
|
||||
_periodDropDown.value = Period.ALL;
|
||||
|
||||
_scores = new Array<MovieClip>();
|
||||
while(true) {
|
||||
|
||||
var score:MovieClip = cast scoreContainer.getChildByName('score${_scores.length}');
|
||||
if (score == null)
|
||||
break;
|
||||
|
||||
new Button(score);
|
||||
_scores.push(score);
|
||||
}
|
||||
|
||||
_limit = _scores.length;
|
||||
}
|
||||
|
||||
override function onReady():Void {
|
||||
super.onReady();
|
||||
|
||||
if (boardId == -1 && !_boardIDSet) {
|
||||
|
||||
#if ng_lite
|
||||
NG.core.calls.scoreBoard.getBoards()
|
||||
.addDataHandler(onBoardsRecieved)
|
||||
.queue();
|
||||
#else
|
||||
if (NG.core.scoreBoards != null)
|
||||
onBoardsLoaded();
|
||||
else
|
||||
NG.core.requestScoreBoards(onBoardsLoaded);
|
||||
#end
|
||||
}
|
||||
|
||||
reload();
|
||||
}
|
||||
|
||||
#if ng_lite
|
||||
function onBoardsRecieved(response:Response<ScoreBoardResult>):Void {
|
||||
|
||||
if (response.success && response.result.success) {
|
||||
|
||||
for (board in response.result.data.scoreboards) {
|
||||
|
||||
NG.core.log('No boardId specified defaulting to ${board.name}');
|
||||
boardId = board.id;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
function onBoardsLoaded():Void {
|
||||
|
||||
for (board in NG.core.scoreBoards) {
|
||||
|
||||
NG.core.log('No boardId specified defaulting to ${board.name}');
|
||||
boardId = board.id;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#end
|
||||
|
||||
/** Used internally to avoid multiple server requests from various property changes in a small time-frame. **/
|
||||
function delayReload():Void {
|
||||
|
||||
addEventListener(Event.EXIT_FRAME, onDelayComplete);
|
||||
}
|
||||
|
||||
function onDelayComplete(e:Event):Void { reload(); }
|
||||
|
||||
public function reload():Void {
|
||||
removeEventListener(Event.EXIT_FRAME, onDelayComplete);
|
||||
|
||||
errorIcon.visible = false;
|
||||
scoreContainer.visible = false;
|
||||
pageField.text = 'page ${page + 1}';
|
||||
|
||||
if (_coreReady && boardId != -1 && _limit > 0 && period != null) {
|
||||
|
||||
loadingIcon.visible = true;
|
||||
|
||||
NG.core.calls.scoreBoard.getScores(boardId, _limit, _limit * page, period, social, tag)
|
||||
.addDataHandler(onScoresReceive)
|
||||
.send();
|
||||
}
|
||||
}
|
||||
|
||||
function onScoresReceive(response:Response<ScoreResult>):Void {
|
||||
|
||||
loadingIcon.visible = false;
|
||||
|
||||
if (response.success && response.result.success) {
|
||||
|
||||
scoreContainer.visible = true;
|
||||
|
||||
var i = _limit;
|
||||
while(i > 0) {
|
||||
i--;
|
||||
|
||||
if (i < response.result.data.scores.length)
|
||||
drawScore(i, response.result.data.scores[i], _scores[i]);
|
||||
else
|
||||
drawScore(i, null, _scores[i]);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
errorIcon.visible = true;
|
||||
errorIcon.gotoAndPlay(1);
|
||||
reloadButton.visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
inline function drawScore(rank:Int, score:Score, asset:MovieClip):Void {
|
||||
|
||||
if (score == null)
|
||||
asset.visible = false;
|
||||
else {
|
||||
|
||||
asset.visible = true;
|
||||
cast (asset.getChildByName("nameField" ), TextField).text = score.user.name;
|
||||
cast (asset.getChildByName("scoreField"), TextField).text = score.formatted_value;
|
||||
cast (asset.getChildByName("rankField" ), TextField).text = Std.string(rank + 1);
|
||||
}
|
||||
}
|
||||
|
||||
function onPrevClick():Void {
|
||||
|
||||
if (page > 0)
|
||||
page--;
|
||||
}
|
||||
|
||||
function onNextClick():Void {
|
||||
|
||||
page++;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package io.newgrounds.swf.common;
|
||||
|
||||
import openfl.events.Event;
|
||||
import openfl.display.MovieClip;
|
||||
|
||||
class BaseAsset extends MovieClip {
|
||||
|
||||
var _coreReady:Bool = false;
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
|
||||
setDefaults();
|
||||
|
||||
if (stage != null)
|
||||
onAdded(null);
|
||||
else
|
||||
addEventListener(Event.ADDED_TO_STAGE, onAdded);
|
||||
}
|
||||
|
||||
function setDefaults():Void { }
|
||||
|
||||
function onAdded(e:Event):Void {
|
||||
|
||||
if (NG.core != null)
|
||||
onReady();
|
||||
else
|
||||
NG.onCoreReady.add(onReady);
|
||||
}
|
||||
|
||||
function onReady():Void {
|
||||
|
||||
_coreReady = true;
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
package io.newgrounds.swf.common;
|
||||
|
||||
import openfl.display.Stage;
|
||||
import openfl.events.Event;
|
||||
import openfl.events.MouseEvent;
|
||||
import openfl.display.MovieClip;
|
||||
|
||||
class Button {
|
||||
|
||||
var _enabled:Bool;
|
||||
public var enabled(get, set):Bool;
|
||||
function get_enabled():Bool { return _enabled; }
|
||||
function set_enabled(value:Bool):Bool {
|
||||
|
||||
if (value != _enabled) {
|
||||
|
||||
_enabled = value;
|
||||
updateEnabled();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public var onClick:Void->Void;
|
||||
public var onOver:Void->Void;
|
||||
public var onOut:Void->Void;
|
||||
|
||||
var _target:MovieClip;
|
||||
var _down:Bool;
|
||||
var _over:Bool;
|
||||
var _foundLabels:Array<String>;
|
||||
|
||||
public function new(target:MovieClip, onClick:Void->Void = null, onOver:Void->Void = null, onOut:Void->Void = null) {
|
||||
|
||||
_target = target;
|
||||
this.onClick = onClick;
|
||||
this.onOver = onOver;
|
||||
this.onOut = onOut;
|
||||
|
||||
_foundLabels = new Array<String>();
|
||||
for (label in _target.currentLabels)
|
||||
_foundLabels.push(label.name);
|
||||
|
||||
_target.stop();
|
||||
_target.addEventListener(Event.ADDED_TO_STAGE, onAdded);
|
||||
if (target.stage != null)
|
||||
onAdded(null);
|
||||
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
function onAdded(e:Event):Void {
|
||||
|
||||
var stage = _target.stage;
|
||||
stage.addEventListener(MouseEvent.MOUSE_UP, mouseHandler);
|
||||
_target.addEventListener(MouseEvent.MOUSE_OVER, mouseHandler);
|
||||
_target.addEventListener(MouseEvent.MOUSE_OUT, mouseHandler);
|
||||
_target.addEventListener(MouseEvent.MOUSE_DOWN, mouseHandler);
|
||||
_target.addEventListener(MouseEvent.CLICK, mouseHandler);
|
||||
|
||||
function selfRemoveEvent(e:Event):Void {
|
||||
|
||||
_target.removeEventListener(Event.REMOVED_FROM_STAGE, selfRemoveEvent);
|
||||
onRemove(e, stage);
|
||||
}
|
||||
_target.addEventListener(Event.REMOVED_FROM_STAGE, selfRemoveEvent);
|
||||
}
|
||||
|
||||
function onRemove(e:Event, stage:Stage):Void {
|
||||
|
||||
stage.removeEventListener(MouseEvent.MOUSE_UP, mouseHandler);
|
||||
_target.removeEventListener(MouseEvent.MOUSE_OVER, mouseHandler);
|
||||
_target.removeEventListener(MouseEvent.MOUSE_OUT, mouseHandler);
|
||||
_target.removeEventListener(MouseEvent.MOUSE_DOWN, mouseHandler);
|
||||
_target.removeEventListener(MouseEvent.CLICK, mouseHandler);
|
||||
}
|
||||
|
||||
function mouseHandler(event:MouseEvent):Void {
|
||||
|
||||
switch(event.type) {
|
||||
|
||||
case MouseEvent.MOUSE_OVER:
|
||||
|
||||
_over = true;
|
||||
|
||||
if (onOver != null)
|
||||
onOver();
|
||||
|
||||
case MouseEvent.MOUSE_OUT:
|
||||
|
||||
_over = false;
|
||||
|
||||
if (onOut != null)
|
||||
onOut();
|
||||
|
||||
case MouseEvent.MOUSE_DOWN:
|
||||
|
||||
_down = true;
|
||||
|
||||
case MouseEvent.MOUSE_UP:
|
||||
|
||||
_down = false;
|
||||
|
||||
case MouseEvent.CLICK:
|
||||
|
||||
if (enabled && onClick != null)
|
||||
onClick();
|
||||
}
|
||||
updateState();
|
||||
}
|
||||
|
||||
function updateEnabled():Void {
|
||||
|
||||
updateState();
|
||||
|
||||
_target.useHandCursor = enabled;
|
||||
_target.buttonMode = enabled;
|
||||
}
|
||||
|
||||
function updateState():Void {
|
||||
|
||||
var state = determineState();
|
||||
|
||||
if (_target.currentLabel != state && _foundLabels.indexOf(state) != -1)
|
||||
_target.gotoAndStop(state);
|
||||
}
|
||||
|
||||
function determineState():String {
|
||||
|
||||
if (enabled) {
|
||||
|
||||
if (_over)
|
||||
return _down ? "down" : "over";
|
||||
|
||||
return "up";
|
||||
|
||||
}
|
||||
return "disabled";
|
||||
}
|
||||
|
||||
public function destroy():Void {
|
||||
|
||||
_target.removeEventListener(Event.ADDED_TO_STAGE, onAdded);
|
||||
|
||||
_target = null;
|
||||
onClick = null;
|
||||
onOver = null;
|
||||
onOut = null;
|
||||
_foundLabels = null;
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
package io.newgrounds.swf.common;
|
||||
|
||||
|
||||
import haxe.ds.StringMap;
|
||||
|
||||
import openfl.display.MovieClip;
|
||||
import openfl.display.Sprite;
|
||||
import openfl.text.TextField;
|
||||
|
||||
class DropDown {
|
||||
|
||||
public var value(default, set):String;
|
||||
function set_value(v:String):String {
|
||||
|
||||
if (this.value == v)
|
||||
return v;
|
||||
|
||||
this.value = v;
|
||||
_selectedLabel.text = _values.get(v);
|
||||
|
||||
if (_onChange != null)
|
||||
_onChange();
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
var _choiceContainer:Sprite;
|
||||
var _selectedLabel:TextField;
|
||||
var _onChange:Void->Void;
|
||||
var _values:StringMap<String>;
|
||||
var _unusedChoices:Array<MovieClip>;
|
||||
|
||||
public function new(target:MovieClip, label:String = "", onChange:Void->Void = null) {
|
||||
|
||||
_onChange = onChange;
|
||||
|
||||
_selectedLabel = cast cast(target.getChildByName("currentItem"), MovieClip).getChildByName("label");
|
||||
_selectedLabel.text = label;
|
||||
|
||||
_values = new StringMap<String>();
|
||||
|
||||
new Button(cast target.getChildByName("button"), onClickExpand);
|
||||
new Button(cast target.getChildByName("currentItem"), onClickExpand);
|
||||
_choiceContainer = new Sprite();
|
||||
_choiceContainer.visible = false;
|
||||
target.addChild(_choiceContainer);
|
||||
|
||||
_unusedChoices = new Array<MovieClip>();
|
||||
while(true) {
|
||||
|
||||
var item:MovieClip = cast target.getChildByName('item${_unusedChoices.length}');
|
||||
if (item == null)
|
||||
break;
|
||||
|
||||
target.removeChild(item);
|
||||
_unusedChoices.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
public function addItem(name:String, value:String):Void {
|
||||
|
||||
_values.set(value, name);
|
||||
|
||||
if (_unusedChoices.length == 0) {
|
||||
|
||||
NG.core.logError('cannot create another dropBox item max=${_choiceContainer.numChildren}');
|
||||
return;
|
||||
}
|
||||
|
||||
var button = _unusedChoices.shift();
|
||||
cast(button.getChildByName("label"), TextField).text = name;
|
||||
_choiceContainer.addChild(button);
|
||||
|
||||
new Button(button, onChoiceClick.bind(value));
|
||||
}
|
||||
|
||||
function onClickExpand():Void {
|
||||
|
||||
_choiceContainer.visible = !_choiceContainer.visible;
|
||||
}
|
||||
|
||||
function onChoiceClick(name:String):Void {
|
||||
|
||||
value = name;
|
||||
|
||||
_choiceContainer.visible = false;
|
||||
}
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
package io.newgrounds.utils;
|
||||
|
||||
import io.newgrounds.NGLite;
|
||||
|
||||
import haxe.Http;
|
||||
import haxe.Timer;
|
||||
|
||||
#if neko
|
||||
import neko.vm.Thread;
|
||||
#elseif java
|
||||
import java.vm.Thread;
|
||||
#elseif cpp
|
||||
import cpp.vm.Thread;
|
||||
#end
|
||||
|
||||
/**
|
||||
* Uses Threading to turn hxcpp's synchronous http requests into asynchronous processes
|
||||
*
|
||||
* @author GeoKureli
|
||||
*/
|
||||
class AsyncHttp {
|
||||
|
||||
inline static var PATH:String = "https://newgrounds.io/gateway_v3.php";
|
||||
|
||||
static public function send
|
||||
( core:NGLite
|
||||
, data:String
|
||||
, onData:String->Void
|
||||
, onError:String->Void
|
||||
, onStatus:Int->Void
|
||||
) {
|
||||
|
||||
core.logVerbose('sending: $data');
|
||||
|
||||
#if (neko || java || cpp)
|
||||
sendAsync(core, data, onData, onError, onStatus);
|
||||
#else
|
||||
sendSync(core, data, onData, onError, onStatus);
|
||||
#end
|
||||
}
|
||||
|
||||
static function sendSync
|
||||
( core:NGLite
|
||||
, data:String
|
||||
, onData:String->Void
|
||||
, onError:String->Void
|
||||
, onStatus:Int->Void
|
||||
):Void {
|
||||
|
||||
var http = new Http(PATH);
|
||||
http.setParameter("input", data);
|
||||
http.onData = onData;
|
||||
http.onError = onError;
|
||||
http.onStatus = onStatus;
|
||||
// #if js http.async = async; #end
|
||||
http.request(true);
|
||||
}
|
||||
|
||||
#if (neko || java || cpp)
|
||||
static var _deadPool:Array<AsyncHttp> = [];
|
||||
static var _livePool:Array<AsyncHttp> = [];
|
||||
static var _map:Map<Int, AsyncHttp> = new Map();
|
||||
static var _timer:Timer;
|
||||
|
||||
static var _count:Int = 0;
|
||||
|
||||
var _core:NGLite;
|
||||
var _key:Int;
|
||||
var _onData:String->Void;
|
||||
var _onError:String->Void;
|
||||
var _onStatus:Int->Void;
|
||||
var _worker:Thread;
|
||||
|
||||
public function new (core:NGLite) {
|
||||
|
||||
_core = core;
|
||||
_worker = Thread.create(sendThreaded);
|
||||
_key = _count++;
|
||||
_map[_key] = this;
|
||||
_core.logVerbose('async http created: $_key');
|
||||
}
|
||||
|
||||
function start(data:String, onData:String->Void, onError:String->Void, onStatus:Int->Void) {
|
||||
|
||||
_core.logVerbose('async http started: $_key');
|
||||
|
||||
if (_livePool.length == 0)
|
||||
startTimer();
|
||||
|
||||
_deadPool.remove(this);
|
||||
_livePool.push(this);
|
||||
|
||||
_onData = onData;
|
||||
_onError = onError;
|
||||
_onStatus = onStatus;
|
||||
_worker.sendMessage({ source:Thread.current(), args:data, key:_key, core:_core });
|
||||
}
|
||||
|
||||
function handleMessage(data:ReplyData):Void {
|
||||
|
||||
_core.logVerbose('handling message: $_key');
|
||||
|
||||
if (data.status != null) {
|
||||
|
||||
_core.logVerbose('\t- status: ${data.status}');
|
||||
_onStatus(cast data.status);
|
||||
return;
|
||||
}
|
||||
|
||||
var tempFunc:Void->Void;
|
||||
if (data.data != null) {
|
||||
|
||||
_core.logVerbose('\t- data');
|
||||
tempFunc = _onData.bind(data.data);
|
||||
|
||||
} else {
|
||||
|
||||
_core.logVerbose('\t- error');
|
||||
tempFunc = _onError.bind(data.error);
|
||||
}
|
||||
|
||||
cleanUp();
|
||||
// Delay the call until destroy so that we're more likely to use a single
|
||||
// thread on daisy-chained calls
|
||||
tempFunc();
|
||||
}
|
||||
|
||||
inline function cleanUp():Void {
|
||||
|
||||
_onData = null;
|
||||
_onError = null;
|
||||
|
||||
_deadPool.push(this);
|
||||
_livePool.remove(this);
|
||||
|
||||
if (_livePool.length == 0)
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
static function sendAsync
|
||||
( core:NGLite
|
||||
, data:String
|
||||
, onData:String->Void
|
||||
, onError:String->Void
|
||||
, onStatus:Int->Void
|
||||
):Void {
|
||||
|
||||
var http:AsyncHttp;
|
||||
if (_deadPool.length == 0)
|
||||
http = new AsyncHttp(core);
|
||||
else
|
||||
http = _deadPool[0];
|
||||
|
||||
http.start(data, onData, onError, onStatus);
|
||||
}
|
||||
|
||||
static function startTimer():Void {
|
||||
|
||||
if (_timer != null)
|
||||
return;
|
||||
|
||||
_timer = new Timer(1000 / 60.0);
|
||||
_timer.run = update;
|
||||
}
|
||||
|
||||
static function stopTimer():Void {
|
||||
|
||||
_timer.stop();
|
||||
_timer = null;
|
||||
}
|
||||
|
||||
static public function update():Void {
|
||||
|
||||
var message:ReplyData = cast Thread.readMessage(false);
|
||||
if (message != null)
|
||||
_map[message.key].handleMessage(message);
|
||||
}
|
||||
|
||||
static function sendThreaded():Void {
|
||||
|
||||
while(true) {
|
||||
|
||||
var data:LoaderData = cast Thread.readMessage(true);
|
||||
data.core.logVerbose('start message received: ${data.key}');
|
||||
|
||||
sendSync
|
||||
( data.core
|
||||
, data.args
|
||||
, function(reply ) { data.source.sendMessage({ key:data.key, data :reply }); }
|
||||
, function(error ) { data.source.sendMessage({ key:data.key, error :error }); }
|
||||
, function(status) { data.source.sendMessage({ key:data.key, status:status }); }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#end
|
||||
}
|
||||
|
||||
|
||||
#if (neko || java || cpp)
|
||||
typedef LoaderData = { source:Thread, key:Int, args:String, core:NGLite };
|
||||
typedef ReplyData = { key:Int, ?data:String, ?error:String, ?status:Null<Int> };
|
||||
#end
|
||||
@@ -1,118 +0,0 @@
|
||||
package io.newgrounds.utils;
|
||||
|
||||
/**
|
||||
* Basically shitty signals, but I didn't want to have external references.
|
||||
**/
|
||||
class Dispatcher {
|
||||
|
||||
var _list:Array<Void->Void>;
|
||||
var _once:Array<Void->Void>;
|
||||
|
||||
public function new() {
|
||||
|
||||
_list = new Array<Void->Void>();
|
||||
_once = new Array<Void->Void>();
|
||||
}
|
||||
|
||||
public function add(handler:Void->Void, once:Bool = false):Bool {
|
||||
|
||||
if (_list.indexOf(handler) != -1) {
|
||||
|
||||
// ---- REMOVE ONCE
|
||||
if (!once && _once.indexOf(handler) != -1)
|
||||
_once.remove(handler);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_list.unshift(handler);
|
||||
if (once)
|
||||
_once.unshift(handler);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline public function addOnce(handler:Void->Void):Bool {
|
||||
|
||||
return add(handler, true);
|
||||
}
|
||||
|
||||
public function remove(handler:Void->Void):Bool {
|
||||
|
||||
_once.remove(handler);
|
||||
return _list.remove(handler);
|
||||
}
|
||||
|
||||
public function dispatch():Void {
|
||||
|
||||
var i = _list.length - 1;
|
||||
while(i >= 0) {
|
||||
|
||||
var handler = _list[i];
|
||||
|
||||
if (_once.remove(handler))
|
||||
_list.remove(handler);
|
||||
|
||||
handler();
|
||||
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TypedDispatcher<T> {
|
||||
|
||||
var _list:Array<T->Void>;
|
||||
var _once:Array<T->Void>;
|
||||
|
||||
public function new() {
|
||||
|
||||
_list = new Array<T->Void>();
|
||||
_once = new Array<T->Void>();
|
||||
}
|
||||
|
||||
public function add(handler:T->Void, once:Bool = false):Bool {
|
||||
|
||||
if (_list.indexOf(handler) != -1) {
|
||||
|
||||
// ---- REMOVE ONCE
|
||||
if (!once && _once.indexOf(handler) != -1)
|
||||
_once.remove(handler);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_list.unshift(handler);
|
||||
if (once)
|
||||
_once.unshift(handler);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline public function addOnce(handler:T->Void):Bool {
|
||||
|
||||
return add(handler, true);
|
||||
}
|
||||
|
||||
public function remove(handler:T->Void):Bool {
|
||||
|
||||
_once.remove(handler);
|
||||
return _list.remove(handler);
|
||||
}
|
||||
|
||||
public function dispatch(arg:T):Void {
|
||||
|
||||
var i = _list.length - 1;
|
||||
while(i >= 0) {
|
||||
|
||||
var handler = _list[i];
|
||||
|
||||
if (_once.remove(handler))
|
||||
_list.remove(handler);
|
||||
|
||||
handler(arg);
|
||||
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||