├── .classpath ├── .gitignore ├── .project ├── .settings ├── org.eclipse.core.resources.prefs ├── org.eclipse.jdt.core.prefs └── org.eclipse.ltk.core.refactoring.prefs ├── LICENSE ├── README.md ├── assets-raw ├── alien │ ├── alien.spine │ └── images │ │ ├── back_foot.png │ │ ├── back_shin.png │ │ ├── back_thigh.png │ │ ├── backarmor.png │ │ ├── blown_up_nck.png │ │ ├── body.png │ │ ├── burst01.png │ │ ├── burst02.png │ │ ├── front_foot.png │ │ ├── front_lower_arm.png │ │ ├── front_shin.png │ │ ├── front_thigh.png │ │ ├── front_upper_arm.png │ │ ├── head.png │ │ ├── jaw.png │ │ ├── lower_back_arm.png │ │ ├── metaljaw.png │ │ ├── splat01.png │ │ ├── splat02.png │ │ ├── splat03.png │ │ └── upper_back_arm.png ├── spineboy │ ├── images │ │ ├── eye_indifferent.png │ │ ├── eye_surprised.png │ │ ├── front_bracer.png │ │ ├── front_fist_closed.png │ │ ├── front_fist_open.png │ │ ├── front_foot.png │ │ ├── front_foot_bend1.png │ │ ├── front_foot_bend2.png │ │ ├── front_shin.png │ │ ├── front_thigh.png │ │ ├── front_upper_arm.png │ │ ├── goggles.png │ │ ├── gun.png │ │ ├── head.png │ │ ├── mouth_grind.png │ │ ├── mouth_oooo.png │ │ ├── mouth_smile.png │ │ ├── muzzle.png │ │ ├── neck.png │ │ ├── rear_bracer.png │ │ ├── rear_foot.png │ │ ├── rear_foot_bend1.png │ │ ├── rear_foot_bend2.png │ │ ├── rear_shin.png │ │ ├── rear_thigh.png │ │ ├── rear_upper_arm.png │ │ ├── torso.png │ │ └── torso_twisted.png │ └── spineboy.spine └── tiles │ ├── decals │ ├── ceiling-lamp-wire-01.png │ ├── ceiling_lamp-01.png │ ├── collision.png │ ├── column-01.png │ ├── column-02.png │ ├── column-03.png │ ├── crate-01.png │ ├── crate-02.png │ ├── crate-3.png │ ├── fill.png │ ├── fusebox-01.png │ ├── metal-01.png │ └── pack.json │ ├── decals02 │ ├── ceiling-01.png │ ├── concrete-01.png │ ├── edge-left-01.png │ ├── ground-01.png │ ├── wall-left-01.png │ ├── wall-left_bottom-01.png │ ├── wall-right-01.png │ └── wall-right_top-01.png │ ├── decals03 │ ├── concrete-02.png │ ├── concrete-03.png │ ├── metal-02.png │ └── metal-03.png │ ├── lights │ ├── light-01.png │ ├── light-02.png │ └── pack.json │ ├── map.tmx │ ├── pack.json │ ├── rock │ ├── pack.json │ ├── rock-01.png │ ├── rock-02.png │ ├── rock-03.png │ └── rock-04.png │ ├── tint01 │ ├── pack.json │ ├── tint-01.png │ ├── tint-02.png │ ├── tint-03.png │ └── tint-04.png │ ├── tint02 │ ├── pack.json │ ├── tint-01.png │ ├── tint-02.png │ ├── tint-03.png │ └── tint-04.png │ ├── tint03 │ ├── tint-01.png │ ├── tint-02.png │ ├── tint-03.png │ ├── tint-04.png │ ├── tint-05.png │ ├── tint-06.png │ ├── tint-07.png │ ├── tint-08.png │ ├── tint-09.png │ ├── tint-10.png │ ├── tint-11.png │ └── tint-12.png │ └── walls │ ├── pack.json │ ├── wall-01.png │ ├── wall-02.png │ ├── wall-03.png │ └── wall-04.png ├── assets ├── alien │ ├── alien.atlas │ ├── alien.json │ └── alien.png ├── bullet-hit.png ├── bullet.png ├── crosshair.png ├── gameOver.png ├── map │ ├── map.atlas │ ├── map.png │ ├── map.tmx │ ├── map2.png │ ├── map3.png │ ├── map4.png │ ├── map5.png │ ├── map6.png │ ├── map7.png │ ├── map8.png │ └── map9.png ├── sounds │ ├── footstep1.ogg │ ├── footstep2.ogg │ ├── hit.ogg │ ├── hurt-alien.ogg │ ├── hurt-player.ogg │ ├── shoot.ogg │ └── squish.ogg ├── spineboy │ ├── spineboy.atlas │ ├── spineboy.json │ └── spineboy.png ├── start.png ├── title.png ├── youLose.png └── youWin.png ├── pom.xml ├── src └── com │ └── esotericsoftware │ └── spine │ └── superspineboy │ ├── Assets.java │ ├── Character.java │ ├── CharacterView.java │ ├── Enemy.java │ ├── EnemyView.java │ ├── Model.java │ ├── Player.java │ ├── PlayerView.java │ ├── SuperSpineboy.java │ ├── UI.java │ └── View.java ├── update-dependencies.cmd └── update-dependencies.sh /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | *.psd 3 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | super-spineboy 4 | NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. 5 | 6 | 7 | 8 | org.eclipse.jdt.core.javabuilder 9 | 10 | 11 | 12 | org.eclipse.jdt.core.javanature 13 | 14 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled 3 | org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled 4 | org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore 5 | org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull 6 | org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= 7 | org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault 8 | org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= 9 | org.eclipse.jdt.core.compiler.annotation.notowning=org.eclipse.jdt.annotation.NotOwning 10 | org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable 11 | org.eclipse.jdt.core.compiler.annotation.nullable.secondary= 12 | org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled 13 | org.eclipse.jdt.core.compiler.annotation.owning=org.eclipse.jdt.annotation.Owning 14 | org.eclipse.jdt.core.compiler.annotation.resourceanalysis=disabled 15 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 16 | org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate 17 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 18 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 19 | org.eclipse.jdt.core.compiler.compliance=1.8 20 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 21 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 22 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 23 | org.eclipse.jdt.core.compiler.problem.APILeak=warning 24 | org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info 25 | org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning 26 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 27 | org.eclipse.jdt.core.compiler.problem.autoboxing=ignore 28 | org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning 29 | org.eclipse.jdt.core.compiler.problem.deadCode=ignore 30 | org.eclipse.jdt.core.compiler.problem.deprecation=ignore 31 | org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled 32 | org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled 33 | org.eclipse.jdt.core.compiler.problem.discouragedReference=warning 34 | org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore 35 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled 36 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 37 | org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore 38 | org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore 39 | org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled 40 | org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore 41 | org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning 42 | org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning 43 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 44 | org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning 45 | org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled 46 | org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning 47 | org.eclipse.jdt.core.compiler.problem.incompatibleOwningContract=warning 48 | org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore 49 | org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore 50 | org.eclipse.jdt.core.compiler.problem.insufficientResourceAnalysis=warning 51 | org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore 52 | org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning 53 | org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore 54 | org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore 55 | org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled 56 | org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore 57 | org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore 58 | org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled 59 | org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore 60 | org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore 61 | org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning 62 | org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning 63 | org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore 64 | org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning 65 | org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning 66 | org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error 67 | org.eclipse.jdt.core.compiler.problem.nullReference=warning 68 | org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error 69 | org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning 70 | org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning 71 | org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore 72 | org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning 73 | org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning 74 | org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore 75 | org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore 76 | org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore 77 | org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning 78 | org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore 79 | org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore 80 | org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore 81 | org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore 82 | org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore 83 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning 84 | org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled 85 | org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning 86 | org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled 87 | org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled 88 | org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info 89 | org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled 90 | org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore 91 | org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning 92 | org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning 93 | org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled 94 | org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore 95 | org.eclipse.jdt.core.compiler.problem.unclosedCloseable=ignore 96 | org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore 97 | org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning 98 | org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning 99 | org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled 100 | org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info 101 | org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore 102 | org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore 103 | org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore 104 | org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning 105 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore 106 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled 107 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled 108 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled 109 | org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore 110 | org.eclipse.jdt.core.compiler.problem.unusedImport=ignore 111 | org.eclipse.jdt.core.compiler.problem.unusedLabel=warning 112 | org.eclipse.jdt.core.compiler.problem.unusedLambdaParameter=warning 113 | org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore 114 | org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore 115 | org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore 116 | org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled 117 | org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=enabled 118 | org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=enabled 119 | org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=ignore 120 | org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore 121 | org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning 122 | org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning 123 | org.eclipse.jdt.core.compiler.release=disabled 124 | org.eclipse.jdt.core.compiler.source=1.8 125 | -------------------------------------------------------------------------------- /.settings/org.eclipse.ltk.core.refactoring.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Spine Runtimes License Agreement 2 | Last updated February 20, 2024. Replaces all prior versions. 3 | 4 | Copyright (c) 2013-2024, Esoteric Software LLC 5 | 6 | Integration of the Spine Runtimes into software or otherwise creating derivative works 7 | of the Spine Runtimes is permitted under the terms and conditions of Section 2 of the 8 | Spine Editor License Agreement: 9 | https://esotericsoftware.com/spine-editor-license 10 | 11 | Otherwise, it is permitted to integrate the Spine Runtimes into software or otherwise 12 | create derivative works of the Spine Runtimes (collectively, "Products"), provided that 13 | each user of the Products must obtain their own Spine Editor license and redistribution 14 | of the Products in any form must include this license and copyright notice. 15 | 16 | THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS OR IMPLIED 17 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR 19 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, 21 | BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY 22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SPINE RUNTIMES, 24 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Super Spineboy](http://i.imgur.com/6jMhdeU.jpg) 2 | 3 | Super Spineboy is a platformer game for Windows, Mac and Linux written using [Spine](https://esotericsoftware.com/) and [spine-libgdx](https://github.com/EsotericSoftware/spine-runtimes/tree/master/spine-libgdx). Spine is a 2D animation tool specifically for games and Super Spineboy shows some of the ways to make use of Spine skeletons and animations in an actual game. 4 | 5 | [![](http://i.imgur.com/7QMVJmt.png)](https://www.youtube.com/watch?v=zAZ_PxxEgDI) 6 | 7 | ## Download 8 | 9 | Super Spineboy can be [downloaded](https://esotericsoftware.com/files/runtimes/superSpineboy.jar) in binary form and run on Windows, Mac or Linux. Java 1.6+ is required. To run Super Spineboy, double click the `superSpineboy.jar` file or run it from the command line: 10 | 11 | ``` 12 | java -jar superSpineboy.jar 13 | ``` 14 | 15 | ## Controls 16 | 17 | * Left click shoots toward the mouse position. Hold to keep shooting. 18 | * `A` is left, `D` is right, `W` is jump. 19 | * Alternatively, `left arrow` is left, `right arrow` is right, `space` is jump. 20 | * Press `alt + enter` or click `Fullscreen` in the menu to run the game fullscreen. 21 | * Press the number keys `1` through `6` to control the game speed, allowing you to see how smooth the animations are and the transitions between animations. 22 | * Press `tilda` or `P` to pause. 23 | * Press `Z` to zoom in/out so you can see the animations more easily. 24 | 25 | ## Gameplay tips 26 | 27 | You may find Super Spineboy difficult at first. The game is relatively short, so the difficulty ramps up quickly. These tips may help you overcome the hordes! 28 | 29 | * Don't move through further into the level until you've killed all the enemies you find. 30 | * Spineboy's weapon shoots very fast, but suffers from reduced accuracy when shot continuously. Cease firing momentarily to regain accuracy. 31 | * You cannot shoot backward when running away, but you can jump while running away and shoot backward in the air. 32 | * Standing your ground and mowing down enemies is great, but there are quickly so many enemies that you get overrun. When this happens, goomba head stomp the enemies. This is key to winning! 33 | * Getting sandwiched between two groups of enemies is a sure way to die. Head stomp your way to one side so you aren't surrounded. 34 | * If the game runs poorly, try unchecking `Background` in the menu. 35 | 36 | ## Source 37 | 38 | Super Spineboy is written in Java and uses OpenGL, [libgdx](http://libgdx.badlogicgames.com/), [Spine](https://esotericsoftware.com/) and [spine-libgdx](https://github.com/EsotericSoftware/spine-runtimes/tree/master/spine-libgdx). A loose [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) design pattern is used for code organization. This makes for a clean separation between the game logic and what is drawn. 39 | 40 | The Super Spineboy source can be downloaded from GitHub using a Git client or as a [zip file](https://github.com/EsotericSoftware/spine-superspineboy/archive/master.zip). To run from source using Eclipse, click `File` -> `Import` -> `Existing projects`. 41 | 42 | ## License 43 | 44 | Super Spineboy is licensed under the [Spine Runtime License](https://github.com/EsotericSoftware/spine-superspineboy/blob/master/LICENSE). Please see the license for full details, but this basically means that if you license [Spine](https://esotericsoftware.com/), you can create derivative works or otherwise use Super Spineboy however you like. 45 | 46 | ## Screenshots 47 | 48 | ![](http://i.imgur.com/TQi1qXB.png) 49 | 50 | ![](http://i.imgur.com/j3RwiU7.png) 51 | 52 | ![](http://i.imgur.com/Y3uAOSj.png) 53 | -------------------------------------------------------------------------------- /assets-raw/alien/alien.spine: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/alien.spine -------------------------------------------------------------------------------- /assets-raw/alien/images/back_foot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/back_foot.png -------------------------------------------------------------------------------- /assets-raw/alien/images/back_shin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/back_shin.png -------------------------------------------------------------------------------- /assets-raw/alien/images/back_thigh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/back_thigh.png -------------------------------------------------------------------------------- /assets-raw/alien/images/backarmor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/backarmor.png -------------------------------------------------------------------------------- /assets-raw/alien/images/blown_up_nck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/blown_up_nck.png -------------------------------------------------------------------------------- /assets-raw/alien/images/body.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/body.png -------------------------------------------------------------------------------- /assets-raw/alien/images/burst01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/burst01.png -------------------------------------------------------------------------------- /assets-raw/alien/images/burst02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/burst02.png -------------------------------------------------------------------------------- /assets-raw/alien/images/front_foot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/front_foot.png -------------------------------------------------------------------------------- /assets-raw/alien/images/front_lower_arm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/front_lower_arm.png -------------------------------------------------------------------------------- /assets-raw/alien/images/front_shin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/front_shin.png -------------------------------------------------------------------------------- /assets-raw/alien/images/front_thigh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/front_thigh.png -------------------------------------------------------------------------------- /assets-raw/alien/images/front_upper_arm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/front_upper_arm.png -------------------------------------------------------------------------------- /assets-raw/alien/images/head.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/head.png -------------------------------------------------------------------------------- /assets-raw/alien/images/jaw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/jaw.png -------------------------------------------------------------------------------- /assets-raw/alien/images/lower_back_arm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/lower_back_arm.png -------------------------------------------------------------------------------- /assets-raw/alien/images/metaljaw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/metaljaw.png -------------------------------------------------------------------------------- /assets-raw/alien/images/splat01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/splat01.png -------------------------------------------------------------------------------- /assets-raw/alien/images/splat02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/splat02.png -------------------------------------------------------------------------------- /assets-raw/alien/images/splat03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/splat03.png -------------------------------------------------------------------------------- /assets-raw/alien/images/upper_back_arm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/alien/images/upper_back_arm.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/eye_indifferent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/eye_indifferent.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/eye_surprised.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/eye_surprised.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/front_bracer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/front_bracer.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/front_fist_closed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/front_fist_closed.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/front_fist_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/front_fist_open.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/front_foot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/front_foot.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/front_foot_bend1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/front_foot_bend1.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/front_foot_bend2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/front_foot_bend2.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/front_shin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/front_shin.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/front_thigh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/front_thigh.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/front_upper_arm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/front_upper_arm.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/goggles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/goggles.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/gun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/gun.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/head.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/head.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/mouth_grind.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/mouth_grind.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/mouth_oooo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/mouth_oooo.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/mouth_smile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/mouth_smile.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/muzzle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/muzzle.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/neck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/neck.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/rear_bracer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/rear_bracer.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/rear_foot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/rear_foot.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/rear_foot_bend1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/rear_foot_bend1.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/rear_foot_bend2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/rear_foot_bend2.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/rear_shin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/rear_shin.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/rear_thigh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/rear_thigh.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/rear_upper_arm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/rear_upper_arm.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/torso.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/torso.png -------------------------------------------------------------------------------- /assets-raw/spineboy/images/torso_twisted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/images/torso_twisted.png -------------------------------------------------------------------------------- /assets-raw/spineboy/spineboy.spine: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/spineboy/spineboy.spine -------------------------------------------------------------------------------- /assets-raw/tiles/decals/ceiling-lamp-wire-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals/ceiling-lamp-wire-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals/ceiling_lamp-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals/ceiling_lamp-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals/collision.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals/collision.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals/column-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals/column-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals/column-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals/column-02.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals/column-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals/column-03.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals/crate-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals/crate-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals/crate-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals/crate-02.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals/crate-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals/crate-3.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals/fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals/fill.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals/fusebox-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals/fusebox-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals/metal-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals/metal-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals/pack.json: -------------------------------------------------------------------------------- 1 | { 2 | combineSubdirectories: true, 3 | } -------------------------------------------------------------------------------- /assets-raw/tiles/decals02/ceiling-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals02/ceiling-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals02/concrete-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals02/concrete-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals02/edge-left-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals02/edge-left-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals02/ground-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals02/ground-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals02/wall-left-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals02/wall-left-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals02/wall-left_bottom-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals02/wall-left_bottom-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals02/wall-right-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals02/wall-right-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals02/wall-right_top-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals02/wall-right_top-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals03/concrete-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals03/concrete-02.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals03/concrete-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals03/concrete-03.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals03/metal-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals03/metal-02.png -------------------------------------------------------------------------------- /assets-raw/tiles/decals03/metal-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/decals03/metal-03.png -------------------------------------------------------------------------------- /assets-raw/tiles/lights/light-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/lights/light-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/lights/light-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/lights/light-02.png -------------------------------------------------------------------------------- /assets-raw/tiles/lights/pack.json: -------------------------------------------------------------------------------- 1 | { 2 | paddingX: 0, 3 | paddingY: 0, 4 | combineSubdirectories: true, 5 | wrapX: ClampToEdge, 6 | wrapY: ClampToEdge, 7 | grid: true 8 | } -------------------------------------------------------------------------------- /assets-raw/tiles/map.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | H4sIAAAAAAAAC+3cO25CQRAEQG7A/W/ryJmFEJreXg9V0gYkvGB6mj+PBwAAAAAAAOzxdL7iAEzTLfuZMZCgW/YzYyBBt+xnxkCCbtnPjIEE3bKfGQMJumU/MwYSdMt+Zgwk6Jb9zBhI0C37mTGQoFv2M2MgQbfsZ8ZAgm7Zz4yBhA3d0v5vwv9wAKZNdcvJHtOPcIf28yKnfyacvtar28AZdo+bvfM4JMPQYfe42Tv5lGHosHvc5JP3vGQYOuweN/kkjzIMHXaPponP2GUYOuweTRP5k2HosHs0TH6nV4ahw+7RMJk7GYYOu8cJqd8S/t43cJ7d44RkzmQYOuweSYnXG39dAzjP7pF0Il8yDB3t/+5znIkDAAAAAAAAAAAAAACb/QC4IhCPAPoAAA== 176 | 177 | 178 | 179 | 180 | H4sIAAAAAAAAC+3dyQ3CUBBEQbOTAJxY8s+SEBrZDPOlX3V98hJBz7IAAAAAAAAAAAAAM3qGfp+8A1Q5hX4e/HkAWOMd+m3yDgAAAAAAAAAAAMBYLqFfB38eANbYh34MfVfc0/cPxR0AAAAAAAD4Xve+tF7bH6EDAMA/de9L67X9FXr3/Q73PwAAAAAAAAAAAAAAIOver0596z539X53+r+t76/e9+6+3+H+BwAAAAAAAAAAAAAAAMDvfQCqWZEeAPoAAA== 181 | 182 | 183 | 184 | 185 | H4sIAAAAAAAAC+3cQQqAIBRFUffQJpoF7X9xzSWQXkR+OQccCSJOLg60NQAAAAAAAAAAqjm7AcDc9knW1g8AEvoBUIv7BwCV6QcACf0AIKEfANw5BvP6AcBb+gFAQj8ASPT92H7ZRa7afgFW4f4BQEI/AAAAAPjT6C0IAAAAAAAAAAAAAAAAAACwDv9XP+O8AAAAAAAAAAAAAAAAAACAr1z7AaWEAPoAAA== 186 | 187 | 188 | 189 | 190 | H4sIAAAAAAAAC+3cywnDMBAEUPeTxJDg/mtLA8YLUcRo8XswJ4F/h/VpZ9sAAAAAAAAAAOjuI5cB4Fx6Pq8egFn25ueHXAaAc+n5vHoAAAAAAAAAAAAAWEt6f2P0HAB+8SzOX5Pv/558/UdxXr0/AAAAAMBdpftBRT8r0FN6fon/B9BTuh9U9LMCPaXnl2ST3t+w/wEAAAAAAAAAAAAAALWq/zndjz3baD92+vuMPn96f8P+BwAAAAAAAAAAAAAAAMD/fQFmZRZyAPoAAA== 191 | 192 | 193 | 194 | 195 | H4sIAAAAAAAAC+3cMQoCQRBE0T1KKaI38P5HM9HASGiEYun3kglmg58Vk+xxAAAAAAAAAABwVpd2AMBy95Oe1wOAprQDhrw/ALrSDhiyHwBdaQcM2Q8AJuwHQFfaAUOf/Xj++G77PQDfvD8AutIOGLIfAEzYD4CutAOG7AcAE/YDoCvtgCH7AcCE/QDoSjsAAABYI+0AAABgjbQDAACANdIOAE6r/X9p9917AJhIOwAAAFgj7QAAAGCN2/t8lE4AAAAAAAAAAAAAAAAA/u8F5Lc02gD6AAA= 196 | 197 | 198 | 199 | 200 | H4sIAAAAAAAAC+3c0QkAIAhAQddp/wUbQUgko7tfQd8ERgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADALOt2QGJ6HwAAAAAAAAAAAAAAAAAAAAAAAAAAAMBvsv/R1Xn3/er+bq/3AwAAAAAAAAAAAHBuAzp5pcAA+gAA 201 | 202 | 203 | 204 | 205 | H4sIAAAAAAAAC+3cQQqAIBAFUI+Q0v3P2qYgohltEWG8t1FBxO131FIAAAAAAAAAACC2Tr4+AAAAAACQe/OsXh0AAAAAAAAAAAAAAAAAAACAp9re1k93AXzN/9i52fcPAAAAAH+2dMYAAACj2qW95otWYu5fAQAAI87ZIcoY5zl3dY8smwAAAGR6d6vkDQAAIHPUMHrvOOpNP5rjDQgAAAAAAAAAAAAAAABA3wZLC7bAAPoAAA== 206 | 207 | 208 | 209 | 210 | H4sIAAAAAAAAC+3cTW6DMBAGUE6UVkG9/9W66qILYhg8DNjvSawQ4x8p8ykJsCwAAAAAAAAAALwnOkYx45qB+6nu6fLjuBnXDNxPdU+XH8fNuGbgfs72ncw+3js/vg+MveWrcf6KMeQHcAdPzw8AasgPACLkBwAR8gOACPkBQIT8ACBiqy//3Yfa817SjNoA1OjZizP7/FbdV+O6Hs9jfPKTXL+Vsa31A2R5en4AUEN+ABAhP4CoyP+fVZ/lq/pFzz2p6HVV87u69tqhLhD3xP6YTX70HzejtvyAWk/sj9nkR/9xM2rLD6jVsz/O+H7sq/cnc/6t+Z0ZN6O2/AAYT4/vHOuOA4CxyA8AIvbkx7r8/y0qcgAwFvkBQMSn/IhmhfwAGJ/8ACBCfsD4Wu9/9n7sc+ez9+fs/KPz2/O8xlZt+QEAAAAAAAAAAAAAAACQ6xeqGQeZAPoAAA== 211 | 212 | 213 | 214 | 215 | H4sIAAAAAAAAC+3ZMQrAIAxAUW9UqPe/W5cKUhpMdSjCeyAuGdw+xFIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYH/17wcAsCX9AGCGfgAwQz8AyKjdfd4HALL0A4BI68Pbjko/AIjoBwAjmX/wZy/0AwD9AGDFl72UfgDQ9P04BrP6AQAAAAAAAAAAAAAAABC7AJuko8IA+gAA 216 | 217 | 218 | 219 | 220 | H4sIAAAAAAAAC+3cQQqDMBRFUdfTSaXQ/W+tdCqlv3lKNck5kKGSUS5q4rIAAJzjUQwA2KraoSUAfKIfACT0A2BOe9d2/QCYk34AkNAPABL6AUCiWtvvDdf/Mtb9UwbgAo5c2z1zAJDQDwASI/Tj1vn9AXo0Qj8A+D/9ACChHwC8tb6rb+mH7wAA80jPgjjzATAeazsAAAAAAAAAAAAAXF91FsS+YICxPM+eAEDI/7G/633+AAAAAAAAAAAAtLEvGAAAAAAAAAAAAKD2ApmR58wA+gAA 221 | 222 | 223 | 224 | 225 | H4sIAAAAAAAAC+3cwQqCQBQFULdltWwR/f93trFNIOJz5DbMOfAQvCqu5iLITBOjeZnhBqCF9Fpm9AfQp/RaZvQH0CdrCgAVv/1x3bhe3ncO0IrvDwAq9AcAFfoDgAr9AUCF/gCg4tsfc/pFAOiK7w8AKvQHABX6A4AK/QFAhf4AWknvDWoyA3BUeh0zmfH/LgAjeyzHy0q+dn6UHM6U3l9ansnvG/ft8VyO74bPBAAAAAAAAAAAAAD+zy39AgAAAAAAAAAAAAA7pfeXlsuP5P7fBQAAAAAAAAAAAHryAX2DmCsA+gAA 226 | 227 | 228 | 229 | 230 | H4sIAAAAAAAAC+3csQ2AMBRDwWwBrMH+w9FTRRHCsXQn0bp8vyJjAAAAAAAAAAAAAADANw77ACw47QOwoL3v7gdARnvf3Q+AjPa+ux8AGe19dz8AMtr77n4AZLT33f0AAAAAAICMe/JLuOwDbGvn+wEAAADQ/n61fYCM9v+n7ANktPfRPkBGex/tA2S099E+QEZ7H+0DZLT30T5ARnsf7QMAAAAAAG/t71fbBwAAAAAAAAAAAOAvD6TMpK4A+gAA 231 | 232 | 233 | 234 | -------------------------------------------------------------------------------- /assets-raw/tiles/pack.json: -------------------------------------------------------------------------------- 1 | { 2 | scale: [ 1 ], 3 | maxWidth: 1024, 4 | stripWhitespaceX: false, 5 | stripWhitespaceY: false, 6 | duplicatePadding: true, 7 | filterMin: Linear, 8 | flattenPaths: false, 9 | scaleSuffix: [ 10 | "", 11 | "", 12 | "", 13 | "", 14 | "" 15 | ], 16 | wrapX: ClampToEdge, 17 | wrapY: ClampToEdge, 18 | alias: true, 19 | debug: false, 20 | edgePadding: false, 21 | pot: true, 22 | premultiplyAlpha: false, 23 | outputFormat: png, 24 | minHeight: 16, 25 | fast: false, 26 | square: false, 27 | limitMemory: true, 28 | minWidth: 16, 29 | paddingX: 2, 30 | paddingY: 2, 31 | grid: false, 32 | combineSubdirectories: false, 33 | maxHeight: 1024, 34 | alphaThreshold: 0, 35 | jpegQuality: 0.9, 36 | bleed: true, 37 | format: RGBA8888, 38 | useIndexes: false, 39 | ignoreBlankImages: true, 40 | filterMag: Linear, 41 | rotation: false 42 | } -------------------------------------------------------------------------------- /assets-raw/tiles/rock/pack.json: -------------------------------------------------------------------------------- 1 | { 2 | paddingX: 0, 3 | paddingY: 0, 4 | combineSubdirectories: true, 5 | wrapX: ClampToEdge, 6 | wrapY: ClampToEdge, 7 | grid: true 8 | } -------------------------------------------------------------------------------- /assets-raw/tiles/rock/rock-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/rock/rock-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/rock/rock-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/rock/rock-02.png -------------------------------------------------------------------------------- /assets-raw/tiles/rock/rock-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/rock/rock-03.png -------------------------------------------------------------------------------- /assets-raw/tiles/rock/rock-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/rock/rock-04.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint01/pack.json: -------------------------------------------------------------------------------- 1 | { 2 | paddingX: 0, 3 | paddingY: 0, 4 | combineSubdirectories: true, 5 | wrapX: ClampToEdge, 6 | wrapY: ClampToEdge, 7 | grid: true 8 | } -------------------------------------------------------------------------------- /assets-raw/tiles/tint01/tint-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint01/tint-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint01/tint-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint01/tint-02.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint01/tint-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint01/tint-03.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint01/tint-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint01/tint-04.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint02/pack.json: -------------------------------------------------------------------------------- 1 | { 2 | paddingX: 0, 3 | paddingY: 0, 4 | combineSubdirectories: true, 5 | wrapX: ClampToEdge, 6 | wrapY: ClampToEdge, 7 | grid: true 8 | } -------------------------------------------------------------------------------- /assets-raw/tiles/tint02/tint-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint02/tint-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint02/tint-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint02/tint-02.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint02/tint-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint02/tint-03.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint02/tint-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint02/tint-04.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint03/tint-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint03/tint-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint03/tint-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint03/tint-02.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint03/tint-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint03/tint-03.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint03/tint-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint03/tint-04.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint03/tint-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint03/tint-05.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint03/tint-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint03/tint-06.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint03/tint-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint03/tint-07.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint03/tint-08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint03/tint-08.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint03/tint-09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint03/tint-09.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint03/tint-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint03/tint-10.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint03/tint-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint03/tint-11.png -------------------------------------------------------------------------------- /assets-raw/tiles/tint03/tint-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/tint03/tint-12.png -------------------------------------------------------------------------------- /assets-raw/tiles/walls/pack.json: -------------------------------------------------------------------------------- 1 | { 2 | paddingX: 0, 3 | paddingY: 0, 4 | combineSubdirectories: true, 5 | wrapX: ClampToEdge, 6 | wrapY: ClampToEdge, 7 | grid: true 8 | } -------------------------------------------------------------------------------- /assets-raw/tiles/walls/wall-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/walls/wall-01.png -------------------------------------------------------------------------------- /assets-raw/tiles/walls/wall-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/walls/wall-02.png -------------------------------------------------------------------------------- /assets-raw/tiles/walls/wall-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/walls/wall-03.png -------------------------------------------------------------------------------- /assets-raw/tiles/walls/wall-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets-raw/tiles/walls/wall-04.png -------------------------------------------------------------------------------- /assets/alien/alien.atlas: -------------------------------------------------------------------------------- 1 | alien.png 2 | size:1361,1032 3 | filter:Linear,Linear 4 | pma:true 5 | back_foot 6 | bounds:326,5,16,11 7 | rotate:90 8 | back_shin 9 | bounds:974,294,42,48 10 | back_thigh 11 | bounds:1301,167,45,47 12 | offsets:2,0,47,47 13 | rotate:90 14 | backarmor 15 | bounds:1018,124,162,181 16 | offsets:0,1,162,182 17 | blown_up_nck 18 | bounds:974,19,153,103 19 | offsets:0,0,153,104 20 | body 21 | bounds:515,318,196,235 22 | rotate:90 23 | burst01 24 | bounds:2,9,285,308 25 | offsets:1,1,286,309 26 | rotate:90 27 | burst02 28 | bounds:611,9,307,361 29 | offsets:4,0,311,361 30 | rotate:90 31 | front_foot 32 | bounds:312,2,19,12 33 | rotate:90 34 | front_lower_arm 35 | bounds:1129,12,110,125 36 | rotate:90 37 | front_shin 38 | bounds:1256,75,49,56 39 | rotate:90 40 | front_thigh 41 | bounds:1182,138,52,54 42 | offsets:2,0,54,54 43 | rotate:90 44 | front_upper_arm 45 | bounds:1182,192,113,55 46 | rotate:90 47 | head 48 | bounds:312,23,297,271 49 | offsets:0,1,297,272 50 | lower_back_arm 51 | bounds:1256,214,101,91 52 | metaljaw 53 | bounds:752,344,242,170 54 | offsets:1,2,243,172 55 | splat01 56 | bounds:515,516,514,503 57 | rotate:90 58 | splat02 59 | bounds:2,296,734,511 60 | rotate:90 61 | splat03 62 | bounds:1020,307,723,339 63 | rotate:90 64 | upper_back_arm 65 | bounds:1239,126,60,86 66 | -------------------------------------------------------------------------------- /assets/alien/alien.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/alien/alien.png -------------------------------------------------------------------------------- /assets/bullet-hit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/bullet-hit.png -------------------------------------------------------------------------------- /assets/bullet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/bullet.png -------------------------------------------------------------------------------- /assets/crosshair.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/crosshair.png -------------------------------------------------------------------------------- /assets/gameOver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/gameOver.png -------------------------------------------------------------------------------- /assets/map/map.atlas: -------------------------------------------------------------------------------- 1 | 2 | map.png 3 | format: RGBA8888 4 | filter: Linear,Linear 5 | repeat: none 6 | decals/ceiling-lamp-wire-01 7 | rotate: false 8 | xy: 0, 66 9 | size: 128, 128 10 | orig: 128, 128 11 | offset: 0, 0 12 | index: -1 13 | decals/ceiling_lamp-01 14 | rotate: false 15 | xy: 514, 584 16 | size: 128, 128 17 | orig: 128, 128 18 | offset: 0, 0 19 | index: -1 20 | decals/collision 21 | rotate: false 22 | xy: 0, 0 23 | size: 64, 64 24 | orig: 64, 64 25 | offset: 0, 0 26 | index: -1 27 | decals/column-01 28 | rotate: false 29 | xy: 0, 650 30 | size: 512, 320 31 | orig: 512, 320 32 | offset: 0, 0 33 | index: -1 34 | decals/column-02 35 | rotate: false 36 | xy: 0, 196 37 | size: 512, 64 38 | orig: 512, 64 39 | offset: 0, 0 40 | index: -1 41 | decals/column-03 42 | rotate: false 43 | xy: 0, 392 44 | size: 512, 256 45 | orig: 512, 256 46 | offset: 0, 0 47 | index: -1 48 | decals/crate-01 49 | rotate: false 50 | xy: 514, 714 51 | size: 256, 256 52 | orig: 256, 256 53 | offset: 0, 0 54 | index: -1 55 | decals/crate-02 56 | rotate: false 57 | xy: 772, 842 58 | size: 128, 128 59 | orig: 128, 128 60 | offset: 0, 0 61 | index: -1 62 | decals/crate-3 63 | rotate: false 64 | xy: 130, 66 65 | size: 128, 128 66 | orig: 128, 128 67 | offset: 0, 0 68 | index: -1 69 | decals/fill 70 | rotate: false 71 | xy: 644, 648 72 | size: 64, 64 73 | orig: 64, 64 74 | offset: 0, 0 75 | index: -1 76 | decals/fusebox-01 77 | rotate: false 78 | xy: 514, 454 79 | size: 128, 128 80 | orig: 128, 128 81 | offset: 0, 0 82 | index: -1 83 | decals/metal-01 84 | rotate: false 85 | xy: 0, 262 86 | size: 512, 128 87 | orig: 512, 128 88 | offset: 0, 0 89 | index: -1 90 | 91 | map2.png 92 | format: RGBA8888 93 | filter: Linear,Linear 94 | repeat: none 95 | decals02/ceiling-01 96 | rotate: false 97 | xy: 0, 840 98 | size: 512, 128 99 | orig: 512, 128 100 | offset: 0, 0 101 | index: -1 102 | decals02/concrete-01 103 | rotate: false 104 | xy: 0, 710 105 | size: 512, 128 106 | orig: 512, 128 107 | offset: 0, 0 108 | index: -1 109 | decals02/edge-left-01 110 | rotate: false 111 | xy: 0, 0 112 | size: 64, 64 113 | orig: 64, 64 114 | offset: 0, 0 115 | index: -1 116 | decals02/ground-01 117 | rotate: false 118 | xy: 0, 580 119 | size: 512, 128 120 | orig: 512, 128 121 | offset: 0, 0 122 | index: -1 123 | decals02/wall-left-01 124 | rotate: false 125 | xy: 0, 66 126 | size: 128, 512 127 | orig: 128, 512 128 | offset: 0, 0 129 | index: -1 130 | decals02/wall-left_bottom-01 131 | rotate: false 132 | xy: 514, 840 133 | size: 128, 128 134 | orig: 128, 128 135 | offset: 0, 0 136 | index: -1 137 | decals02/wall-right-01 138 | rotate: false 139 | xy: 130, 66 140 | size: 128, 512 141 | orig: 128, 512 142 | offset: 0, 0 143 | index: -1 144 | decals02/wall-right_top-01 145 | rotate: false 146 | xy: 260, 450 147 | size: 128, 128 148 | orig: 128, 128 149 | offset: 0, 0 150 | index: -1 151 | 152 | map3.png 153 | format: RGBA8888 154 | filter: Linear,Linear 155 | repeat: none 156 | decals03/concrete-02 157 | rotate: false 158 | xy: 0, 390 159 | size: 512, 128 160 | orig: 512, 128 161 | offset: 0, 0 162 | index: -1 163 | decals03/concrete-03 164 | rotate: false 165 | xy: 0, 260 166 | size: 512, 128 167 | orig: 512, 128 168 | offset: 0, 0 169 | index: -1 170 | decals03/metal-02 171 | rotate: false 172 | xy: 0, 130 173 | size: 512, 128 174 | orig: 512, 128 175 | offset: 0, 0 176 | index: -1 177 | decals03/metal-03 178 | rotate: false 179 | xy: 0, 0 180 | size: 512, 128 181 | orig: 512, 128 182 | offset: 0, 0 183 | index: -1 184 | 185 | map4.png 186 | format: RGBA8888 187 | filter: Linear,Linear 188 | repeat: none 189 | lights/light-01 190 | rotate: false 191 | xy: 0, 0 192 | size: 512, 512 193 | orig: 512, 512 194 | offset: 0, 0 195 | index: -1 196 | lights/light-02 197 | rotate: false 198 | xy: 512, 0 199 | size: 512, 512 200 | orig: 512, 512 201 | offset: 0, 0 202 | index: -1 203 | 204 | map5.png 205 | format: RGBA8888 206 | filter: Linear,Linear 207 | repeat: none 208 | rock/rock-01 209 | rotate: false 210 | xy: 0, 0 211 | size: 512, 512 212 | orig: 512, 512 213 | offset: 0, 0 214 | index: -1 215 | rock/rock-02 216 | rotate: false 217 | xy: 512, 0 218 | size: 512, 512 219 | orig: 512, 512 220 | offset: 0, 0 221 | index: -1 222 | rock/rock-03 223 | rotate: false 224 | xy: 0, 512 225 | size: 512, 512 226 | orig: 512, 512 227 | offset: 0, 0 228 | index: -1 229 | rock/rock-04 230 | rotate: false 231 | xy: 512, 512 232 | size: 512, 512 233 | orig: 512, 512 234 | offset: 0, 0 235 | index: -1 236 | 237 | map6.png 238 | format: RGBA8888 239 | filter: Linear,Linear 240 | repeat: none 241 | tint01/tint-01 242 | rotate: false 243 | xy: 0, 0 244 | size: 512, 512 245 | orig: 512, 512 246 | offset: 0, 0 247 | index: -1 248 | tint01/tint-02 249 | rotate: false 250 | xy: 512, 0 251 | size: 512, 512 252 | orig: 512, 512 253 | offset: 0, 0 254 | index: -1 255 | tint01/tint-03 256 | rotate: false 257 | xy: 0, 512 258 | size: 512, 512 259 | orig: 512, 512 260 | offset: 0, 0 261 | index: -1 262 | tint01/tint-04 263 | rotate: false 264 | xy: 512, 512 265 | size: 512, 512 266 | orig: 512, 512 267 | offset: 0, 0 268 | index: -1 269 | 270 | map7.png 271 | format: RGBA8888 272 | filter: Linear,Linear 273 | repeat: none 274 | tint02/tint-01 275 | rotate: false 276 | xy: 0, 0 277 | size: 512, 512 278 | orig: 512, 512 279 | offset: 0, 0 280 | index: -1 281 | tint02/tint-02 282 | rotate: false 283 | xy: 512, 0 284 | size: 512, 512 285 | orig: 512, 512 286 | offset: 0, 0 287 | index: -1 288 | tint02/tint-03 289 | rotate: false 290 | xy: 0, 512 291 | size: 512, 512 292 | orig: 512, 512 293 | offset: 0, 0 294 | index: -1 295 | tint02/tint-04 296 | rotate: false 297 | xy: 512, 512 298 | size: 512, 512 299 | orig: 512, 512 300 | offset: 0, 0 301 | index: -1 302 | 303 | map8.png 304 | format: RGBA8888 305 | filter: Linear,Linear 306 | repeat: none 307 | tint03/tint-01 308 | rotate: false 309 | xy: 260, 64 310 | size: 64, 64 311 | orig: 64, 64 312 | offset: 0, 0 313 | index: -1 314 | tint03/tint-02 315 | rotate: false 316 | xy: 390, 194 317 | size: 64, 64 318 | orig: 64, 64 319 | offset: 0, 0 320 | index: -1 321 | tint03/tint-03 322 | rotate: false 323 | xy: 904, 388 324 | size: 64, 64 325 | orig: 64, 64 326 | offset: 0, 0 327 | index: -1 328 | tint03/tint-04 329 | rotate: false 330 | xy: 0, 260 331 | size: 512, 192 332 | orig: 512, 192 333 | offset: 0, 0 334 | index: -1 335 | tint03/tint-05 336 | rotate: false 337 | xy: 0, 130 338 | size: 128, 128 339 | orig: 128, 128 340 | offset: 0, 0 341 | index: -1 342 | tint03/tint-06 343 | rotate: false 344 | xy: 514, 324 345 | size: 128, 128 346 | orig: 128, 128 347 | offset: 0, 0 348 | index: -1 349 | tint03/tint-07 350 | rotate: false 351 | xy: 0, 0 352 | size: 128, 128 353 | orig: 128, 128 354 | offset: 0, 0 355 | index: -1 356 | tint03/tint-08 357 | rotate: false 358 | xy: 130, 130 359 | size: 128, 128 360 | orig: 128, 128 361 | offset: 0, 0 362 | index: -1 363 | tint03/tint-09 364 | rotate: false 365 | xy: 644, 324 366 | size: 128, 128 367 | orig: 128, 128 368 | offset: 0, 0 369 | index: -1 370 | tint03/tint-10 371 | rotate: false 372 | xy: 130, 0 373 | size: 128, 128 374 | orig: 128, 128 375 | offset: 0, 0 376 | index: -1 377 | tint03/tint-11 378 | rotate: false 379 | xy: 260, 130 380 | size: 128, 128 381 | orig: 128, 128 382 | offset: 0, 0 383 | index: -1 384 | tint03/tint-12 385 | rotate: false 386 | xy: 774, 324 387 | size: 128, 128 388 | orig: 128, 128 389 | offset: 0, 0 390 | index: -1 391 | 392 | map9.png 393 | format: RGBA8888 394 | filter: Linear,Linear 395 | repeat: none 396 | walls/wall-01 397 | rotate: false 398 | xy: 0, 0 399 | size: 512, 512 400 | orig: 512, 512 401 | offset: 0, 0 402 | index: -1 403 | walls/wall-02 404 | rotate: false 405 | xy: 512, 0 406 | size: 512, 512 407 | orig: 512, 512 408 | offset: 0, 0 409 | index: -1 410 | walls/wall-03 411 | rotate: false 412 | xy: 0, 512 413 | size: 512, 512 414 | orig: 512, 512 415 | offset: 0, 0 416 | index: -1 417 | walls/wall-04 418 | rotate: false 419 | xy: 512, 512 420 | size: 512, 512 421 | orig: 512, 512 422 | offset: 0, 0 423 | index: -1 424 | -------------------------------------------------------------------------------- /assets/map/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/map/map.png -------------------------------------------------------------------------------- /assets/map/map.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | H4sIAAAAAAAAC+3cO25CQRAEQG7A/W/ryJmFEJreXg9V0gYkvGB6mj+PBwAAAAAAAOzxdL7iAEzTLfuZMZCgW/YzYyBBt+xnxkCCbtnPjIEE3bKfGQMJumU/MwYSdMt+Zgwk6Jb9zBhI0C37mTGQoFv2M2MgQbfsZ8ZAgm7Zz4yBhA3d0v5vwv9wAKZNdcvJHtOPcIf28yKnfyacvtar28AZdo+bvfM4JMPQYfe42Tv5lGHosHvc5JP3vGQYOuweN/kkjzIMHXaPponP2GUYOuweTRP5k2HosHs0TH6nV4ahw+7RMJk7GYYOu8cJqd8S/t43cJ7d44RkzmQYOuweSYnXG39dAzjP7pF0Il8yDB3t/+5znIkDAAAAAAAAAAAAAACb/QC4IhCPAPoAAA== 179 | 180 | 181 | 182 | 183 | H4sIAAAAAAAAC+3dyQ3CUBBEQbOTAJxY8s+SEBrZDPOlX3V98hJBz7IAAAAAAAAAAAAAM3qGfp+8A1Q5hX4e/HkAWOMd+m3yDgAAAAAAAAAAAMBYLqFfB38eANbYh34MfVfc0/cPxR0AAAAAAAD4Xve+tF7bH6EDAMA/de9L67X9FXr3/Q73PwAAAAAAAAAAAAAAIOver0596z539X53+r+t76/e9+6+3+H+BwAAAAAAAAAAAAAAAMDvfQCqWZEeAPoAAA== 184 | 185 | 186 | 187 | 188 | H4sIAAAAAAAAC+3cQQqAIBRFUffQJpoF7X9xzSWQXkR+OQccCSJOLg60NQAAAAAAAAAAqjm7AcDc9knW1g8AEvoBUIv7BwCV6QcACf0AIKEfANw5BvP6AcBb+gFAQj8ASPT92H7ZRa7afgFW4f4BQEI/AAAAAPjT6C0IAAAAAAAAAAAAAAAAAACwDv9XP+O8AAAAAAAAAAAAAAAAAACAr1z7AaWEAPoAAA== 189 | 190 | 191 | 192 | 193 | H4sIAAAAAAAAC+3cywnDMBAEUPeTxJDg/mtLA8YLUcRo8XswJ4F/h/VpZ9sAAAAAAAAAAOjuI5cB4Fx6Pq8egFn25ueHXAaAc+n5vHoAAAAAAAAAAAAAWEt6f2P0HAB+8SzOX5Pv/558/UdxXr0/AAAAAMBdpftBRT8r0FN6fon/B9BTuh9U9LMCPaXnl2ST3t+w/wEAAAAAAAAAAAAAALWq/zndjz3baD92+vuMPn96f8P+BwAAAAAAAAAAAAAAAMD/fQFmZRZyAPoAAA== 194 | 195 | 196 | 197 | 198 | H4sIAAAAAAAAC+3cMQoCQRBE0T1KKaI38P5HM9HASGiEYun3kglmg58Vk+xxAAAAAAAAAABwVpd2AMBy95Oe1wOAprQDhrw/ALrSDhiyHwBdaQcM2Q8AJuwHQFfaAUOf/Xj++G77PQDfvD8AutIOGLIfAEzYD4CutAOG7AcAE/YDoCvtgCH7AcCE/QDoSjsAAABYI+0AAABgjbQDAACANdIOAE6r/X9p9917AJhIOwAAAFgj7QAAAGCN2/t8lE4AAAAAAAAAAAAAAAAA/u8F5Lc02gD6AAA= 199 | 200 | 201 | 202 | 203 | H4sIAAAAAAAAC+3c0QkAIAhAQddp/wUbQUgko7tfQd8ERgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADALOt2QGJ6HwAAAAAAAAAAAAAAAAAAAAAAAAAAAMBvsv/R1Xn3/er+bq/3AwAAAAAAAAAAAHBuAzp5pcAA+gAA 204 | 205 | 206 | 207 | 208 | H4sIAAAAAAAAC+3cQQqAIBAFUI+Q0v3P2qYgohltEWG8t1FBxO131FIAAAAAAAAAACC2Tr4+AAAAAACQe/OsXh0AAAAAAAAAAAAAAAAAAACAp9re1k93AXzN/9i52fcPAAAAAH+2dMYAAACj2qW95otWYu5fAQAAI87ZIcoY5zl3dY8smwAAAGR6d6vkDQAAIHPUMHrvOOpNP5rjDQgAAAAAAAAAAAAAAABA3wZLC7bAAPoAAA== 209 | 210 | 211 | 212 | 213 | H4sIAAAAAAAAC+3cTW6DMBAGUE6UVkG9/9W66qILYhg8DNjvSawQ4x8p8ykJsCwAAAAAAAAAALwnOkYx45qB+6nu6fLjuBnXDNxPdU+XH8fNuGbgfs72ncw+3js/vg+MveWrcf6KMeQHcAdPzw8AasgPACLkBwAR8gOACPkBQIT8ACBiqy//3Yfa817SjNoA1OjZizP7/FbdV+O6Hs9jfPKTXL+Vsa31A2R5en4AUEN+ABAhP4CoyP+fVZ/lq/pFzz2p6HVV87u69tqhLhD3xP6YTX70HzejtvyAWk/sj9nkR/9xM2rLD6jVsz/O+H7sq/cnc/6t+Z0ZN6O2/AAYT4/vHOuOA4CxyA8AIvbkx7r8/y0qcgAwFvkBQMSn/IhmhfwAGJ/8ACBCfsD4Wu9/9n7sc+ez9+fs/KPz2/O8xlZt+QEAAAAAAAAAAAAAAACQ6xeqGQeZAPoAAA== 214 | 215 | 216 | 217 | 218 | H4sIAAAAAAAAC+3ZMQrAIAxAUW9UqPe/W5cKUhpMdSjCeyAuGdw+xFIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYH/17wcAsCX9AGCGfgAwQz8AyKjdfd4HALL0A4BI68Pbjko/AIjoBwAjmX/wZy/0AwD9AGDFl72UfgDQ9P04BrP6AQAAAAAAAAAAAAAAABC7AJuko8IA+gAA 219 | 220 | 221 | 222 | 223 | H4sIAAAAAAAAC+3cQQqDMBRFUdfTSaXQ/W+tdCqlv3lKNck5kKGSUS5q4rIAAJzjUQwA2KraoSUAfKIfACT0A2BOe9d2/QCYk34AkNAPABL6AUCiWtvvDdf/Mtb9UwbgAo5c2z1zAJDQDwASI/Tj1vn9AXo0Qj8A+D/9ACChHwC8tb6rb+mH7wAA80jPgjjzATAeazsAAAAAAAAAAAAAXF91FsS+YICxPM+eAEDI/7G/633+AAAAAAAAAAAAtLEvGAAAAAAAAAAAAKD2ApmR58wA+gAA 224 | 225 | 226 | 227 | 228 | H4sIAAAAAAAAC+3cwQqCQBQFULdltWwR/f93trFNIOJz5DbMOfAQvCqu5iLITBOjeZnhBqCF9Fpm9AfQp/RaZvQH0CdrCgAVv/1x3bhe3ncO0IrvDwAq9AcAFfoDgAr9AUCF/gCg4tsfc/pFAOiK7w8AKvQHABX6A4AK/QFAhf4AWknvDWoyA3BUeh0zmfH/LgAjeyzHy0q+dn6UHM6U3l9ansnvG/ft8VyO74bPBAAAAAAAAAAAAAD+zy39AgAAAAAAAAAAAAA7pfeXlsuP5P7fBQAAAAAAAAAAAHryAX2DmCsA+gAA 229 | 230 | 231 | 232 | 233 | H4sIAAAAAAAAC+3csQ2AMBRDwWwBrMH+w9FTRRHCsXQn0bp8vyJjAAAAAAAAAAAAAADANw77ACw47QOwoL3v7gdARnvf3Q+AjPa+ux8AGe19dz8AMtr77n4AZLT33f0AAAAAAICMe/JLuOwDbGvn+wEAAADQ/n61fYCM9v+n7ANktPfRPkBGex/tA2S099E+QEZ7H+0DZLT30T5ARnsf7QMAAAAAAG/t71fbBwAAAAAAAAAAAOAvD6TMpK4A+gAA 234 | 235 | 236 | 237 | -------------------------------------------------------------------------------- /assets/map/map2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/map/map2.png -------------------------------------------------------------------------------- /assets/map/map3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/map/map3.png -------------------------------------------------------------------------------- /assets/map/map4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/map/map4.png -------------------------------------------------------------------------------- /assets/map/map5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/map/map5.png -------------------------------------------------------------------------------- /assets/map/map6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/map/map6.png -------------------------------------------------------------------------------- /assets/map/map7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/map/map7.png -------------------------------------------------------------------------------- /assets/map/map8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/map/map8.png -------------------------------------------------------------------------------- /assets/map/map9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/map/map9.png -------------------------------------------------------------------------------- /assets/sounds/footstep1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/sounds/footstep1.ogg -------------------------------------------------------------------------------- /assets/sounds/footstep2.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/sounds/footstep2.ogg -------------------------------------------------------------------------------- /assets/sounds/hit.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/sounds/hit.ogg -------------------------------------------------------------------------------- /assets/sounds/hurt-alien.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/sounds/hurt-alien.ogg -------------------------------------------------------------------------------- /assets/sounds/hurt-player.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/sounds/hurt-player.ogg -------------------------------------------------------------------------------- /assets/sounds/shoot.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/sounds/shoot.ogg -------------------------------------------------------------------------------- /assets/sounds/squish.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/sounds/squish.ogg -------------------------------------------------------------------------------- /assets/spineboy/spineboy.atlas: -------------------------------------------------------------------------------- 1 | spineboy.png 2 | size:1056,542 3 | filter:Linear,Linear 4 | pma:true 5 | eye_indifferent 6 | bounds:961,274,93,89 7 | eye_surprised 8 | bounds:961,183,93,89 9 | front_bracer 10 | bounds:369,59,58,80 11 | front_fist_closed 12 | bounds:828,94,75,82 13 | rotate:90 14 | front_fist_open 15 | bounds:777,6,86,87 16 | rotate:90 17 | front_foot 18 | bounds:429,77,126,68 19 | offsets:0,1,126,69 20 | front_foot_bend1 21 | bounds:698,99,128,70 22 | front_foot_bend2 23 | bounds:604,132,108,92 24 | offsets:0,0,108,93 25 | rotate:90 26 | front_shin 27 | bounds:184,59,80,183 28 | offsets:1,1,82,184 29 | rotate:90 30 | front_thigh 31 | bounds:912,262,47,112 32 | offsets:0,0,48,112 33 | front_upper_arm 34 | bounds:257,3,54,97 35 | rotate:90 36 | goggles 37 | bounds:701,376,261,164 38 | offsets:0,2,261,166 39 | gun 40 | bounds:701,171,209,203 41 | offsets:0,0,210,203 42 | head 43 | bounds:428,242,271,298 44 | mouth_grind 45 | bounds:961,122,93,59 46 | mouth_oooo 47 | bounds:866,33,93,59 48 | mouth_smile 49 | bounds:961,61,93,59 50 | muzzle 51 | bounds:2,141,424,399 52 | offsets:20,1,462,400 53 | neck 54 | bounds:2,5,35,41 55 | offsets:0,0,36,41 56 | rotate:90 57 | rear_bracer 58 | bounds:184,2,55,71 59 | offsets:0,1,56,72 60 | rotate:90 61 | rear_foot 62 | bounds:557,70,113,60 63 | rear_foot_bend1 64 | bounds:429,9,117,66 65 | rear_foot_bend2 66 | bounds:672,14,103,83 67 | rear_shin 68 | bounds:964,365,74,175 69 | offsets:1,1,75,178 70 | rear_thigh 71 | bounds:548,11,57,103 72 | offsets:8,1,65,104 73 | rotate:90 74 | rear_upper_arm 75 | bounds:912,173,47,87 76 | torso 77 | bounds:2,42,97,180 78 | offsets:0,0,98,180 79 | rotate:90 80 | torso_twisted 81 | bounds:428,147,93,174 82 | offsets:1,0,94,174 83 | rotate:90 84 | -------------------------------------------------------------------------------- /assets/spineboy/spineboy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/spineboy/spineboy.png -------------------------------------------------------------------------------- /assets/start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/start.png -------------------------------------------------------------------------------- /assets/title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/title.png -------------------------------------------------------------------------------- /assets/youLose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/youLose.png -------------------------------------------------------------------------------- /assets/youWin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EsotericSoftware/spine-superspineboy/c3d1901e2fc8f01812878fd1837aca24fe485ae3/assets/youWin.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 4.0.0 7 | 8 | com.esotericsoftware 9 | super-spineboy 10 | 1.0-SNAPSHOT 11 | 12 | super-spineboy 13 | 14 | 15 | UTF-8 16 | 16 17 | 16 18 | 19 | 20 | 21 | 22 | com.esotericsoftware.spine 23 | spine-libgdx 24 | 4.2.7 25 | 26 | 27 | com.badlogicgames.gdx 28 | gdx 29 | 1.13.0 30 | 31 | 32 | com.badlogicgames.gdx 33 | gdx-backend-lwjgl 34 | 1.13.0 35 | 36 | 37 | com.badlogicgames.gdx 38 | gdx-platform 39 | 1.13.0 40 | natives-desktop 41 | 42 | 43 | 44 | 45 | src 46 | bin 47 | 48 | 49 | assets 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | maven-clean-plugin 58 | 3.1.0 59 | 60 | 61 | 62 | 63 | maven-resources-plugin 64 | 3.0.2 65 | 66 | 67 | maven-compiler-plugin 68 | 3.8.0 69 | 70 | 71 | maven-surefire-plugin 72 | 2.22.1 73 | 74 | 75 | maven-jar-plugin 76 | 3.0.2 77 | 78 | 79 | maven-install-plugin 80 | 2.5.2 81 | 82 | 83 | maven-deploy-plugin 84 | 2.8.2 85 | 86 | 87 | 88 | 89 | maven-site-plugin 90 | 3.7.1 91 | 92 | 93 | maven-project-info-reports-plugin 94 | 3.0.0 95 | 96 | 97 | 98 | 99 | org.apache.maven.plugins 100 | maven-eclipse-plugin 101 | 2.10 102 | 103 | true 104 | 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /src/com/esotericsoftware/spine/superspineboy/Assets.java: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes License Agreement 3 | * Last updated February 20, 2024. Replaces all prior versions. 4 | * 5 | * Copyright (c) 2013-2024, Esoteric Software LLC 6 | * 7 | * Integration of the Spine Runtimes into software or otherwise creating derivative works 8 | * of the Spine Runtimes is permitted under the terms and conditions of Section 2 of the 9 | * Spine Editor License Agreement: 10 | * https://esotericsoftware.com/spine-editor-license 11 | * 12 | * Otherwise, it is permitted to integrate the Spine Runtimes into software or otherwise 13 | * create derivative works of the Spine Runtimes (collectively, "Products"), provided that 14 | * each user of the Products must obtain their own Spine Editor license and redistribution 15 | * of the Products in any form must include this license and copyright notice. 16 | * 17 | * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, 22 | * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SPINE RUNTIMES, 25 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *****************************************************************************/ 27 | 28 | package com.esotericsoftware.spine.superspineboy; 29 | 30 | import static com.esotericsoftware.spine.superspineboy.Model.*; 31 | 32 | import com.esotericsoftware.spine.Animation; 33 | import com.esotericsoftware.spine.AnimationStateData; 34 | import com.esotericsoftware.spine.SkeletonData; 35 | import com.esotericsoftware.spine.SkeletonJson; 36 | import com.esotericsoftware.spine.superspineboy.Model.State; 37 | import com.esotericsoftware.spine.superspineboy.View.StateView; 38 | 39 | import com.badlogic.gdx.Gdx; 40 | import com.badlogic.gdx.audio.Sound; 41 | import com.badlogic.gdx.graphics.Texture; 42 | import com.badlogic.gdx.graphics.Texture.TextureFilter; 43 | import com.badlogic.gdx.graphics.g2d.TextureAtlas; 44 | import com.badlogic.gdx.graphics.g2d.TextureRegion; 45 | import com.badlogic.gdx.utils.ObjectMap; 46 | 47 | /** Centralized place to load and store assets. */ 48 | class Assets { 49 | TextureAtlas playerAtlas, enemyAtlas; 50 | TextureRegion bulletRegion, hitRegion, crosshair; 51 | TextureRegion titleRegion, gameOverRegion, youLoseRegion, youWinRegion, startRegion; 52 | 53 | SkeletonData playerSkeletonData, enemySkeletonData; 54 | AnimationStateData playerAnimationData, enemyAnimationData; 55 | ObjectMap playerStates = new ObjectMap(), enemyStates = new ObjectMap(); 56 | 57 | Assets () { 58 | bulletRegion = loadRegion("bullet.png"); 59 | hitRegion = loadRegion("bullet-hit.png"); 60 | titleRegion = loadRegion("title.png"); 61 | gameOverRegion = loadRegion("gameOver.png"); 62 | youLoseRegion = loadRegion("youLose.png"); 63 | youWinRegion = loadRegion("youWin.png"); 64 | startRegion = loadRegion("start.png"); 65 | crosshair = loadRegion("crosshair.png"); 66 | 67 | SoundEffect.shoot.sound = Gdx.audio.newSound(Gdx.files.internal("sounds/shoot.ogg")); 68 | SoundEffect.hit.sound = Gdx.audio.newSound(Gdx.files.internal("sounds/hit.ogg")); 69 | SoundEffect.footstep1.sound = Gdx.audio.newSound(Gdx.files.internal("sounds/footstep1.ogg")); 70 | SoundEffect.footstep2.sound = Gdx.audio.newSound(Gdx.files.internal("sounds/footstep2.ogg")); 71 | SoundEffect.squish.sound = Gdx.audio.newSound(Gdx.files.internal("sounds/squish.ogg")); 72 | SoundEffect.squish.volume = 0.6f; 73 | SoundEffect.hurtPlayer.sound = Gdx.audio.newSound(Gdx.files.internal("sounds/hurt-player.ogg")); 74 | SoundEffect.hurtAlien.sound = Gdx.audio.newSound(Gdx.files.internal("sounds/hurt-alien.ogg")); 75 | SoundEffect.hurtAlien.volume = 0.5f; 76 | 77 | loadPlayerAssets(); 78 | loadEnemyAssets(); 79 | } 80 | 81 | TextureRegion loadRegion (String name) { 82 | Texture texture = new Texture(name); 83 | texture.setFilter(TextureFilter.Nearest, TextureFilter.Linear); 84 | return new TextureRegion(texture); 85 | } 86 | 87 | void loadPlayerAssets () { 88 | playerAtlas = new TextureAtlas(Gdx.files.internal("spineboy/spineboy.atlas")); 89 | 90 | SkeletonJson json = new SkeletonJson(playerAtlas); 91 | json.setScale(Player.height / Player.heightSource); 92 | playerSkeletonData = json.readSkeletonData(Gdx.files.internal("spineboy/spineboy.json")); 93 | 94 | playerAnimationData = new AnimationStateData(playerSkeletonData); 95 | playerAnimationData.setDefaultMix(0.2f); 96 | setMix(playerAnimationData, "idle", "run", 0.3f); 97 | setMix(playerAnimationData, "run", "idle", 0.1f); 98 | setMix(playerAnimationData, "shoot", "shoot", 0); 99 | 100 | setupState(playerStates, State.death, playerSkeletonData, "death", false); 101 | StateView idle = setupState(playerStates, State.idle, playerSkeletonData, "idle", true); 102 | StateView jump = setupState(playerStates, State.jump, playerSkeletonData, "jump", false); 103 | StateView run = setupState(playerStates, State.run, playerSkeletonData, "run", true); 104 | if (idle.animation != null) run.startTimes.put(idle.animation, 8 * fps); 105 | if (jump.animation != null) run.startTimes.put(jump.animation, 22 * fps); 106 | StateView fall = setupState(playerStates, State.fall, playerSkeletonData, "jump", false); 107 | fall.defaultStartTime = 22 * fps; 108 | } 109 | 110 | void loadEnemyAssets () { 111 | enemyAtlas = new TextureAtlas(Gdx.files.internal("alien/alien.atlas")); 112 | 113 | SkeletonJson json = new SkeletonJson(enemyAtlas); 114 | json.setScale(Enemy.height / Enemy.heightSource); 115 | enemySkeletonData = json.readSkeletonData(Gdx.files.internal("alien/alien.json")); 116 | 117 | enemyAnimationData = new AnimationStateData(enemySkeletonData); 118 | enemyAnimationData.setDefaultMix(0.1f); 119 | 120 | setupState(enemyStates, State.idle, enemySkeletonData, "run", true); 121 | setupState(enemyStates, State.jump, enemySkeletonData, "jump", true); 122 | setupState(enemyStates, State.run, enemySkeletonData, "run", true); 123 | setupState(enemyStates, State.death, enemySkeletonData, "death", false); 124 | setupState(enemyStates, State.fall, enemySkeletonData, "run", false); 125 | } 126 | 127 | void setMix (AnimationStateData data, String from, String to, float mix) { 128 | Animation fromAnimation = data.getSkeletonData().findAnimation(from); 129 | Animation toAnimation = data.getSkeletonData().findAnimation(to); 130 | if (fromAnimation == null || toAnimation == null) return; 131 | data.setMix(fromAnimation, toAnimation, mix); 132 | } 133 | 134 | StateView setupState (ObjectMap map, State state, SkeletonData skeletonData, String name, boolean loop) { 135 | StateView stateView = new StateView(); 136 | stateView.animation = skeletonData.findAnimation(name); 137 | stateView.loop = loop; 138 | map.put(state, stateView); 139 | return stateView; 140 | } 141 | 142 | void dispose () { 143 | playerAtlas.dispose(); 144 | enemyAtlas.dispose(); 145 | } 146 | 147 | enum SoundEffect { 148 | shoot, hit, footstep1, footstep2, squish, hurtPlayer, hurtAlien; 149 | 150 | Sound sound; 151 | float volume = 1; 152 | 153 | void play () { 154 | sound.play(volume); 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/com/esotericsoftware/spine/superspineboy/Character.java: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes License Agreement 3 | * Last updated February 20, 2024. Replaces all prior versions. 4 | * 5 | * Copyright (c) 2013-2024, Esoteric Software LLC 6 | * 7 | * Integration of the Spine Runtimes into software or otherwise creating derivative works 8 | * of the Spine Runtimes is permitted under the terms and conditions of Section 2 of the 9 | * Spine Editor License Agreement: 10 | * https://esotericsoftware.com/spine-editor-license 11 | * 12 | * Otherwise, it is permitted to integrate the Spine Runtimes into software or otherwise 13 | * create derivative works of the Spine Runtimes (collectively, "Products"), provided that 14 | * each user of the Products must obtain their own Spine Editor license and redistribution 15 | * of the Products in any form must include this license and copyright notice. 16 | * 17 | * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, 22 | * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SPINE RUNTIMES, 25 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *****************************************************************************/ 27 | 28 | package com.esotericsoftware.spine.superspineboy; 29 | 30 | import static com.esotericsoftware.spine.superspineboy.Model.*; 31 | 32 | import com.esotericsoftware.spine.superspineboy.Model.State; 33 | 34 | import com.badlogic.gdx.math.Rectangle; 35 | import com.badlogic.gdx.math.Vector2; 36 | 37 | /** The model class for an enemy or player that moves around the map. */ 38 | class Character { 39 | static float minVelocityX = 0.001f, maxVelocityY = 20f; 40 | static float groundedTime = 0.15f; 41 | static float dampingGroundX = 36, dampingAirX = 15, collideDampingX = 0.7f; 42 | static float runGroundX = 80, runAirSame = 45, runAirOpposite = 45; 43 | 44 | Model model; 45 | Vector2 position = new Vector2(); 46 | Vector2 velocity = new Vector2(); 47 | State state = State.idle; 48 | float stateTime; 49 | float dir; 50 | float airTime; 51 | Rectangle rect = new Rectangle(); 52 | boolean stateChanged; 53 | float hp; 54 | 55 | float maxVelocityX; 56 | float collisionOffsetY; 57 | float jumpVelocity; 58 | 59 | Character (Model model) { 60 | this.model = model; 61 | } 62 | 63 | void setState (State newState) { 64 | if ((state == newState && state != State.fall) || state == State.death) return; 65 | state = newState; 66 | stateTime = 0; 67 | stateChanged = true; 68 | } 69 | 70 | void update (float delta) { 71 | stateTime += delta; 72 | 73 | // If moving downward, change state to fall. 74 | if (velocity.y < 0 && state != State.jump && state != State.fall) { 75 | setState(State.fall); 76 | setGrounded(false); 77 | } 78 | 79 | // Apply gravity. 80 | velocity.y -= gravity * delta; 81 | if (velocity.y < 0 && -velocity.y > maxVelocityY) velocity.y = Math.signum(velocity.y) * maxVelocityY; 82 | 83 | boolean grounded = isGrounded(); 84 | 85 | // Damping reduces velocity so the character eventually comes to a complete stop. 86 | float damping = (grounded ? dampingGroundX : dampingAirX) * delta; 87 | if (velocity.x > 0) 88 | velocity.x = Math.max(0, velocity.x - damping); 89 | else 90 | velocity.x = Math.min(0, velocity.x + damping); 91 | if (Math.abs(velocity.x) < minVelocityX && grounded) { 92 | velocity.x = 0; 93 | setState(State.idle); 94 | } 95 | 96 | velocity.scl(delta); // Change velocity from units/sec to units since last frame. 97 | collideX(); 98 | collideY(); 99 | position.add(velocity); 100 | velocity.scl(1 / delta); // Change velocity back. 101 | } 102 | 103 | boolean isGrounded () { 104 | // The character is considered grounded for a short time after leaving the ground, making jumping over gaps easier. 105 | return airTime < groundedTime; 106 | } 107 | 108 | void setGrounded (boolean grounded) { 109 | airTime = grounded ? 0 : groundedTime; 110 | } 111 | 112 | boolean collideX () { 113 | rect.x = position.x + velocity.x; 114 | rect.y = position.y + collisionOffsetY; 115 | 116 | int x; 117 | if (velocity.x >= 0) 118 | x = (int)(rect.x + rect.width); 119 | else 120 | x = (int)rect.x; 121 | int startY = (int)rect.y; 122 | int endY = (int)(rect.y + rect.height); 123 | for (Rectangle tile : model.getCollisionTiles(x, startY, x, endY)) { 124 | if (!rect.overlaps(tile)) continue; 125 | if (velocity.x >= 0) 126 | position.x = tile.x - rect.width; 127 | else 128 | position.x = tile.x + tile.width; 129 | velocity.x *= collideDampingX; 130 | return true; 131 | } 132 | return false; 133 | } 134 | 135 | boolean collideY () { 136 | rect.x = position.x; 137 | rect.y = position.y + velocity.y + collisionOffsetY; 138 | 139 | int y; 140 | if (velocity.y > 0) 141 | y = (int)(rect.y + rect.height); 142 | else 143 | y = (int)rect.y; 144 | int startX = (int)rect.x; 145 | int endX = (int)(rect.x + rect.width); 146 | for (Rectangle tile : model.getCollisionTiles(startX, y, endX, y)) { 147 | if (!rect.overlaps(tile)) continue; 148 | if (velocity.y > 0) 149 | position.y = tile.y - rect.height; 150 | else { 151 | position.y = tile.y + tile.height; 152 | if (state == State.jump) setState(State.idle); 153 | setGrounded(true); 154 | } 155 | velocity.y = 0; 156 | return true; 157 | } 158 | return false; 159 | } 160 | 161 | void moveLeft (float delta) { 162 | float adjust; 163 | if (isGrounded()) { 164 | adjust = runGroundX; 165 | setState(State.run); 166 | } else 167 | adjust = velocity.x <= 0 ? runAirSame : runAirOpposite; 168 | if (velocity.x > -maxVelocityX) velocity.x = Math.max(velocity.x - adjust * delta, -maxVelocityX); 169 | dir = -1; 170 | } 171 | 172 | void moveRight (float delta) { 173 | float adjust; 174 | if (isGrounded()) { 175 | adjust = runGroundX; 176 | setState(State.run); 177 | } else 178 | adjust = velocity.x >= 0 ? runAirSame : runAirOpposite; 179 | if (velocity.x < maxVelocityX) velocity.x = Math.min(velocity.x + adjust * delta, maxVelocityX); 180 | dir = 1; 181 | } 182 | 183 | void jump () { 184 | velocity.y += jumpVelocity; 185 | setState(State.jump); 186 | setGrounded(false); 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /src/com/esotericsoftware/spine/superspineboy/CharacterView.java: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes License Agreement 3 | * Last updated February 20, 2024. Replaces all prior versions. 4 | * 5 | * Copyright (c) 2013-2024, Esoteric Software LLC 6 | * 7 | * Integration of the Spine Runtimes into software or otherwise creating derivative works 8 | * of the Spine Runtimes is permitted under the terms and conditions of Section 2 of the 9 | * Spine Editor License Agreement: 10 | * https://esotericsoftware.com/spine-editor-license 11 | * 12 | * Otherwise, it is permitted to integrate the Spine Runtimes into software or otherwise 13 | * create derivative works of the Spine Runtimes (collectively, "Products"), provided that 14 | * each user of the Products must obtain their own Spine Editor license and redistribution 15 | * of the Products in any form must include this license and copyright notice. 16 | * 17 | * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, 22 | * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SPINE RUNTIMES, 25 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *****************************************************************************/ 27 | 28 | package com.esotericsoftware.spine.superspineboy; 29 | 30 | import com.esotericsoftware.spine.Animation; 31 | import com.esotericsoftware.spine.AnimationState; 32 | import com.esotericsoftware.spine.AnimationState.TrackEntry; 33 | import com.esotericsoftware.spine.Skeleton; 34 | import com.esotericsoftware.spine.superspineboy.View.StateView; 35 | 36 | /** The view class for an enemy or player that moves around the map. */ 37 | class CharacterView { 38 | View view; 39 | Model model; 40 | Skeleton skeleton; 41 | AnimationState animationState; 42 | 43 | CharacterView (View view) { 44 | this.view = view; 45 | model = view.model; 46 | } 47 | 48 | boolean setAnimation (StateView state, boolean force) { 49 | // Changes the current animation on track 0 of the AnimationState, if needed. 50 | Animation animation = state.animation; 51 | TrackEntry current = animationState.getCurrent(0); 52 | Animation oldAnimation = current == null ? null : current.getAnimation(); 53 | if (force || oldAnimation != animation) { 54 | if (state.animation == null) return true; 55 | TrackEntry entry = animationState.setAnimation(0, state.animation, state.loop); 56 | if (oldAnimation != null) entry.setTrackTime(state.startTimes.get(oldAnimation, state.defaultStartTime)); 57 | if (!state.loop) entry.setTrackEnd(Float.MAX_VALUE); 58 | return true; 59 | } 60 | return false; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/com/esotericsoftware/spine/superspineboy/Enemy.java: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes License Agreement 3 | * Last updated February 20, 2024. Replaces all prior versions. 4 | * 5 | * Copyright (c) 2013-2024, Esoteric Software LLC 6 | * 7 | * Integration of the Spine Runtimes into software or otherwise creating derivative works 8 | * of the Spine Runtimes is permitted under the terms and conditions of Section 2 of the 9 | * Spine Editor License Agreement: 10 | * https://esotericsoftware.com/spine-editor-license 11 | * 12 | * Otherwise, it is permitted to integrate the Spine Runtimes into software or otherwise 13 | * create derivative works of the Spine Runtimes (collectively, "Products"), provided that 14 | * each user of the Products must obtain their own Spine Editor license and redistribution 15 | * of the Products in any form must include this license and copyright notice. 16 | * 17 | * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, 22 | * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SPINE RUNTIMES, 25 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *****************************************************************************/ 27 | 28 | package com.esotericsoftware.spine.superspineboy; 29 | 30 | import static com.esotericsoftware.spine.superspineboy.Model.*; 31 | 32 | import com.esotericsoftware.spine.superspineboy.Model.State; 33 | 34 | import com.badlogic.gdx.math.MathUtils; 35 | 36 | /** The model class for an enemy. */ 37 | class Enemy extends Character { 38 | static float heightSource = 398, width = 105 * scale, height = 200 * scale; 39 | 40 | static float maxVelocityMinX = 4f, maxVelocityMaxX = 8.5f, maxVelocityAirX = 19f; 41 | static float hpWeak = 1, hpSmall = 2, hpNormal = 3, hpStrong = 5, hpBecomesBig = 8, hpBig = 20; 42 | static float corpseTime = 5 * 60, fadeTime = 3; 43 | static float jumpDistanceNormal = 20, jumpDelayNormal = 1.6f, jumpVelocityNormal = 12, jumpVelocityBig = 18; 44 | static float sizeSmall = 0.5f, sizeBig = 2.5f, sizeStrong = 1.3f, bigDuration = 2, smallCount = 14; 45 | 46 | static float normalKnockbackX = 19, normalKnockbackY = 9, bigKnockbackX = 12, bigKnockbackY = 6; 47 | static float collisionDelay = 0.3f; 48 | 49 | float deathTimer = corpseTime; 50 | float maxVelocityGroundX; 51 | float collisionTimer; 52 | float jumpDelayTimer, jumpDistance, jumpDelay; 53 | Type type; 54 | float size = 1; 55 | float bigTimer; 56 | float spawnSmallsTimer; 57 | boolean move; 58 | boolean forceJump; 59 | int collisions; 60 | float knockbackX = normalKnockbackX, knockbackY = normalKnockbackY; 61 | 62 | // This is here for convenience, the model should never touch the view. 63 | EnemyView view; 64 | 65 | Enemy (Model model, Type type) { 66 | super(model); 67 | this.type = type; 68 | 69 | rect.width = width; 70 | rect.height = height; 71 | 72 | maxVelocityGroundX = MathUtils.random(maxVelocityMinX, maxVelocityMaxX); 73 | maxVelocityX = maxVelocityGroundX; 74 | jumpVelocity = jumpVelocityNormal; 75 | jumpDelay = jumpDelayNormal; 76 | jumpDistance = jumpDistanceNormal; 77 | 78 | if (type == Type.big) { 79 | size = sizeBig; 80 | rect.width = width * size * 0.7f; 81 | rect.height = height * size * 0.7f; 82 | hp = hpBig; 83 | knockbackX = normalKnockbackX; 84 | knockbackY = normalKnockbackY; 85 | } else if (type == Type.small) { 86 | size = sizeSmall; 87 | rect.width = width * size; 88 | rect.height = height * size; 89 | hp = hpSmall; 90 | } else if (type == Type.weak) 91 | hp = hpWeak; 92 | else if (type == Type.becomesBig) 93 | hp = hpBecomesBig; 94 | else if (type == Type.strong) { 95 | hp = hpStrong; 96 | size = sizeStrong; 97 | jumpVelocity *= 1.5f; 98 | jumpDistance *= 1.4f; 99 | } else 100 | hp = hpNormal; 101 | 102 | jumpDelayTimer = MathUtils.random(0, jumpDelay); 103 | } 104 | 105 | void update (float delta) { 106 | stateChanged = false; 107 | 108 | if (state == State.death) { 109 | if (type == Type.becomesBig && size == 1) { 110 | bigTimer = bigDuration; 111 | collisionTimer = bigDuration; 112 | state = State.run; 113 | hp = hpBig; 114 | knockbackX = bigKnockbackX; 115 | knockbackY = bigKnockbackY; 116 | type = Type.big; 117 | jumpVelocity = jumpVelocityBig; 118 | } else if (type == Type.big) { 119 | spawnSmallsTimer = 0.8333f; 120 | type = Type.normal; 121 | } 122 | } 123 | 124 | // Enemy grows to a big enemy. 125 | if (bigTimer > 0) { 126 | bigTimer -= delta; 127 | size = 1 + (sizeBig - 1) * (1 - Math.max(0, bigTimer / bigDuration)); 128 | rect.width = width * size * 0.7f; 129 | rect.height = height * size * 0.7f; 130 | } 131 | 132 | // Big enemy explodes into small ones. 133 | if (spawnSmallsTimer > 0) { 134 | spawnSmallsTimer -= delta; 135 | if (spawnSmallsTimer < 0) { 136 | for (int i = 0; i < smallCount; i++) { 137 | Enemy small = new Enemy(model, Type.small); 138 | small.position.set(position.x, position.y + 2); 139 | small.velocity.x = MathUtils.random(5, 15) * (MathUtils.randomBoolean() ? 1 : -1); 140 | small.velocity.y = MathUtils.random(10, 25); 141 | small.setGrounded(false); 142 | model.enemies.add(small); 143 | } 144 | } 145 | } 146 | 147 | // Nearly dead enemies jump at the player right away. 148 | if (hp == 1 && type != Type.weak && type != Type.small) jumpDelayTimer = 0; 149 | 150 | // Kill enemies stuck in the map or those that have somehow fallen out of the map. 151 | if (state != State.death && (hp <= 0 || position.y < -100 || collisions > 100)) { 152 | state = State.death; 153 | hp = 0; 154 | } 155 | 156 | // Simple enemy AI. 157 | boolean grounded = isGrounded(); 158 | if (grounded) move = true; 159 | collisionTimer -= delta; 160 | maxVelocityX = grounded ? maxVelocityGroundX : maxVelocityAirX; 161 | if (state == State.death) 162 | deathTimer -= delta; 163 | else if (collisionTimer < 0) { 164 | if (model.player.hp == 0) { 165 | // Enemies win, jump for joy! 166 | if (grounded && velocity.x == 0) { 167 | jumpVelocity = jumpVelocityNormal / 2; 168 | dir = -dir; 169 | jump(); 170 | } 171 | } else { 172 | // Jump if within range of the player. 173 | if (grounded && (forceJump || Math.abs(model.player.position.x - position.x) < jumpDistance)) { 174 | jumpDelayTimer -= delta; 175 | if (state != State.jump && jumpDelayTimer < 0 && position.y <= model.player.position.y) { 176 | jump(); 177 | jumpDelayTimer = MathUtils.random(0, jumpDelay); 178 | forceJump = false; 179 | } 180 | } 181 | // Move toward the player. 182 | if (move) { 183 | if (model.player.position.x > position.x) { 184 | if (velocity.x >= 0) moveRight(delta); 185 | } else if (velocity.x <= 0) // 186 | moveLeft(delta); 187 | } 188 | } 189 | } 190 | 191 | int previousCollision = collisions; 192 | super.update(delta); 193 | if (!grounded || collisions == previousCollision) collisions = 0; 194 | } 195 | 196 | boolean collideX () { 197 | boolean result = super.collideX(); 198 | if (result) { 199 | // If grounded and collided with the map, jump to avoid the obstacle. 200 | if (isGrounded()) forceJump = true; 201 | collisions++; 202 | } 203 | return result; 204 | } 205 | 206 | enum Type { 207 | weak, normal, strong, becomesBig, big, small 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /src/com/esotericsoftware/spine/superspineboy/EnemyView.java: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes License Agreement 3 | * Last updated February 20, 2024. Replaces all prior versions. 4 | * 5 | * Copyright (c) 2013-2024, Esoteric Software LLC 6 | * 7 | * Integration of the Spine Runtimes into software or otherwise creating derivative works 8 | * of the Spine Runtimes is permitted under the terms and conditions of Section 2 of the 9 | * Spine Editor License Agreement: 10 | * https://esotericsoftware.com/spine-editor-license 11 | * 12 | * Otherwise, it is permitted to integrate the Spine Runtimes into software or otherwise 13 | * create derivative works of the Spine Runtimes (collectively, "Products"), provided that 14 | * each user of the Products must obtain their own Spine Editor license and redistribution 15 | * of the Products in any form must include this license and copyright notice. 16 | * 17 | * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, 22 | * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SPINE RUNTIMES, 25 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *****************************************************************************/ 27 | 28 | package com.esotericsoftware.spine.superspineboy; 29 | 30 | import com.esotericsoftware.spine.Animation; 31 | import com.esotericsoftware.spine.AnimationState; 32 | import com.esotericsoftware.spine.AnimationState.AnimationStateAdapter; 33 | import com.esotericsoftware.spine.Bone; 34 | import com.esotericsoftware.spine.Event; 35 | import com.esotericsoftware.spine.EventData; 36 | import com.esotericsoftware.spine.Skeleton; 37 | import com.esotericsoftware.spine.Skeleton.Physics; 38 | import com.esotericsoftware.spine.Slot; 39 | import com.esotericsoftware.spine.attachments.Attachment; 40 | import com.esotericsoftware.spine.superspineboy.Assets.SoundEffect; 41 | import com.esotericsoftware.spine.superspineboy.Enemy.Type; 42 | 43 | import com.badlogic.gdx.graphics.Color; 44 | import com.badlogic.gdx.math.MathUtils; 45 | 46 | /** The view class for an enemy. */ 47 | class EnemyView extends CharacterView { 48 | Enemy enemy; 49 | Animation hitAnimation; 50 | Slot headSlot; 51 | Attachment burstHeadAttachment; 52 | Color headColor; 53 | 54 | EnemyView (final View view, Enemy enemy) { 55 | super(view); 56 | this.enemy = enemy; 57 | 58 | skeleton = new Skeleton(view.assets.enemySkeletonData); 59 | burstHeadAttachment = skeleton.getAttachment("head", "burst01"); 60 | headSlot = skeleton.findSlot("head"); 61 | hitAnimation = skeleton.getData().findAnimation("hit"); 62 | 63 | animationState = new AnimationState(view.assets.enemyAnimationData); 64 | 65 | // Play squish sound when enemies die. 66 | final EventData squishEvent = view.assets.enemySkeletonData.findEvent("squish"); 67 | animationState.addListener(new AnimationStateAdapter() { 68 | public void event (int trackIndex, Event event) { 69 | if (event.getData() == squishEvent) SoundEffect.squish.play(); 70 | } 71 | }); 72 | 73 | // Enemies have slight color variations. 74 | if (enemy.type == Type.strong) 75 | headColor = new Color(1, 0.6f, 1, 1); 76 | else 77 | headColor = new Color(MathUtils.random(0.8f, 1), MathUtils.random(0.8f, 1), MathUtils.random(0.8f, 1), 1); 78 | headSlot.getColor().set(headColor); 79 | } 80 | 81 | void update (float delta) { 82 | // Change head attachment for enemies that are about to die. 83 | if (enemy.hp == 1 && enemy.type != Type.weak) headSlot.setAttachment(burstHeadAttachment); 84 | 85 | // Change color for big enemies. 86 | if (enemy.type == Type.big) headSlot.getColor().set(headColor).lerp(0, 1, 1, 1, 1 - enemy.bigTimer / Enemy.bigDuration); 87 | 88 | skeleton.setX(enemy.position.x + Enemy.width / 2); 89 | skeleton.setY(enemy.position.y); 90 | 91 | if (!setAnimation(view.assets.enemyStates.get(enemy.state), enemy.stateChanged)) animationState.update(delta); 92 | animationState.apply(skeleton); 93 | 94 | Bone root = skeleton.getRootBone(); 95 | root.setScaleX(root.getScaleX() * enemy.size); 96 | root.setScaleY(root.getScaleY() * enemy.size); 97 | 98 | skeleton.setScaleX(enemy.dir); 99 | skeleton.updateWorldTransform(Physics.none); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/com/esotericsoftware/spine/superspineboy/Model.java: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes License Agreement 3 | * Last updated February 20, 2024. Replaces all prior versions. 4 | * 5 | * Copyright (c) 2013-2024, Esoteric Software LLC 6 | * 7 | * Integration of the Spine Runtimes into software or otherwise creating derivative works 8 | * of the Spine Runtimes is permitted under the terms and conditions of Section 2 of the 9 | * Spine Editor License Agreement: 10 | * https://esotericsoftware.com/spine-editor-license 11 | * 12 | * Otherwise, it is permitted to integrate the Spine Runtimes into software or otherwise 13 | * create derivative works of the Spine Runtimes (collectively, "Products"), provided that 14 | * each user of the Products must obtain their own Spine Editor license and redistribution 15 | * of the Products in any form must include this license and copyright notice. 16 | * 17 | * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, 22 | * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SPINE RUNTIMES, 25 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *****************************************************************************/ 27 | 28 | package com.esotericsoftware.spine.superspineboy; 29 | 30 | import com.esotericsoftware.spine.superspineboy.Enemy.Type; 31 | 32 | import com.badlogic.gdx.maps.tiled.AtlasTmxMapLoader; 33 | import com.badlogic.gdx.maps.tiled.TiledMap; 34 | import com.badlogic.gdx.maps.tiled.TiledMapTileLayer; 35 | import com.badlogic.gdx.maps.tiled.TiledMapTileLayer.Cell; 36 | import com.badlogic.gdx.math.Interpolation; 37 | import com.badlogic.gdx.math.MathUtils; 38 | import com.badlogic.gdx.math.Rectangle; 39 | import com.badlogic.gdx.math.Vector2; 40 | import com.badlogic.gdx.utils.Array; 41 | import com.badlogic.gdx.utils.FloatArray; 42 | import com.badlogic.gdx.utils.Pools; 43 | 44 | /** The core of the game logic. The model manages all game information but knows nothing about the view, ie it knows nothing about 45 | * how this information might be drawn to the screen. This model-view separation is a clean way to organize the code. */ 46 | class Model { 47 | static float scale = 1 / 64f; 48 | static float gravity = 32; 49 | static float fps = 1 / 30f; 50 | static float gameOverSlowdown = 5.5f; 51 | static int mapCollisionLayer = 0; 52 | 53 | SuperSpineboy controller; 54 | Player player; 55 | TiledMap map; 56 | TiledMapTileLayer collisionLayer; 57 | Array tiles = new Array(); 58 | float timeScale = 1; 59 | Array triggers = new Array(); 60 | FloatArray bullets = new FloatArray(); 61 | Array enemies = new Array(); 62 | Vector2 temp = new Vector2(); 63 | float gameOverTimer; 64 | 65 | Model (SuperSpineboy controller) { 66 | this.controller = controller; 67 | 68 | map = new AtlasTmxMapLoader().load("map/map.tmx"); 69 | collisionLayer = (TiledMapTileLayer)map.getLayers().get(mapCollisionLayer); 70 | 71 | restart(); 72 | } 73 | 74 | void restart () { 75 | player = new Player(this); 76 | player.position.set(4, 8); 77 | 78 | bullets.clear(); 79 | enemies.clear(); 80 | gameOverTimer = 0; 81 | 82 | // Setup triggers to spawn enemies based on the x coordinate of the player. 83 | triggers.clear(); 84 | addTrigger(17, 17 + 22, 8, Type.normal, 2); 85 | addTrigger(17, 17 + 22, 8, Type.strong, 1); 86 | addTrigger(31, 31 + 22, 8, Type.normal, 3); 87 | addTrigger(43, 43 + 22, 8, Type.strong, 3); 88 | addTrigger(64, 64 + 22, 8, Type.normal, 10); 89 | addTrigger(64, 64 + 29, 8, Type.strong, 1); 90 | addTrigger(76, 76 - 19, 8, Type.strong, 2); 91 | addTrigger(87, 87 - 19, 8, Type.normal, 2); 92 | addTrigger(97, 97 - 19, 8, Type.normal, 2); 93 | addTrigger(100, 100 + 34, 8, Type.strong, 2); 94 | addTrigger(103, 103 + 34, 8, Type.normal, 4); 95 | addTrigger(125, 60 - 19, 8, Type.normal, 10); 96 | addTrigger(125, 125 - 19, 8, Type.weak, 10); 97 | addTrigger(125, 125 - 45, 8, Type.becomesBig, 1); 98 | addTrigger(125, 125 + 22, 22, Type.normal, 5); 99 | addTrigger(125, 125 + 32, 22, Type.normal, 2); 100 | addTrigger(125, 220, 23, Type.strong, 3); 101 | addTrigger(158, 158 - 19, 8, Type.weak, 10); 102 | addTrigger(158, 158 - 23, 8, Type.strong, 1); 103 | addTrigger(158, 158 + 22, 23, Type.normal, 3); 104 | addTrigger(165, 165 + 22, 23, Type.strong, 4); 105 | addTrigger(176, 176 + 22, 23, Type.normal, 12); 106 | addTrigger(176, 176 + 22, 23, Type.weak, 10); 107 | addTrigger(176, 151, 8, Type.strong, 1); 108 | addTrigger(191, 191 - 19, 23, Type.normal, 5); 109 | addTrigger(191, 191 - 19, 23, Type.weak, 15); 110 | addTrigger(191, 191 - 27, 23, Type.strong, 2); 111 | addTrigger(191, 191 + 34, 23, Type.weak, 10); 112 | addTrigger(191, 191 + 34, 23, Type.weak, 8); 113 | addTrigger(191, 191 + 34, 23, Type.normal, 2); 114 | addTrigger(191, 191 + 42, 23, Type.strong, 2); 115 | addTrigger(213, 213 + 22, 23, Type.normal, 3); 116 | addTrigger(213, 213 + 22, 23, Type.strong, 3); 117 | addTrigger(213, 213 - 19, 23, Type.normal, 7); 118 | addTrigger(246, 247 - 30, 23, Type.strong, 7); 119 | addTrigger(246, 225, 23, Type.normal, 2); 120 | addTrigger(246, 220, 23, Type.becomesBig, 3); 121 | } 122 | 123 | void addTrigger (float triggerX, float spawnX, float spawnY, Type type, int count) { 124 | Trigger trigger = new Trigger(); 125 | trigger.x = triggerX; 126 | triggers.add(trigger); 127 | int offset = spawnX > triggerX ? 2 : -2; 128 | for (int i = 0; i < count; i++) { 129 | Enemy enemy = new Enemy(this, type); 130 | enemy.position.set(spawnX, spawnY); 131 | trigger.enemies.add(enemy); 132 | spawnX += offset; 133 | } 134 | } 135 | 136 | void update (float delta) { 137 | if (player.hp == 0) { 138 | gameOverTimer += delta / getTimeScale() * timeScale; // Isn't affected by player death time scaling. 139 | controller.eventGameOver(false); 140 | } 141 | updateEnemies(delta); 142 | updateBullets(delta); 143 | player.update(delta); 144 | updateTriggers(); 145 | } 146 | 147 | void updateTriggers () { 148 | for (int i = 0, n = triggers.size; i < n; i++) { 149 | Trigger trigger = triggers.get(i); 150 | if (player.position.x > trigger.x) { 151 | enemies.addAll(trigger.enemies); 152 | triggers.removeIndex(i); 153 | break; 154 | } 155 | } 156 | } 157 | 158 | void updateEnemies (float delta) { 159 | int alive = 0; 160 | for (int i = enemies.size - 1; i >= 0; i--) { 161 | Enemy enemy = enemies.get(i); 162 | enemy.update(delta); 163 | if (enemy.deathTimer < 0) { 164 | enemies.removeIndex(i); 165 | continue; 166 | } 167 | if (enemy.hp > 0) alive++; 168 | if (enemy.hp > 0 && player.hp > 0) { 169 | if (enemy.collisionTimer < 0 && enemy.rect.overlaps(player.rect)) { 170 | if (enemy.rect.y + enemy.rect.height * 0.6f < player.rect.y) { 171 | // Enemy head bounce. 172 | float bounceX = Player.headBounceX 173 | * (enemy.position.x + enemy.rect.width / 2 < player.position.x + player.rect.width / 2 ? 1 : -1); 174 | 175 | enemy.collisionTimer = Enemy.collisionDelay; 176 | enemy.velocity.x -= bounceX; 177 | enemy.velocity.y -= 10f; 178 | enemy.setGrounded(false); 179 | enemy.hp -= 2; 180 | if (enemy.hp <= 0) 181 | enemy.state = State.death; 182 | else 183 | enemy.state = State.fall; 184 | 185 | player.velocity.x = bounceX; 186 | player.velocity.y = Player.headBounceY; 187 | player.setGrounded(false); 188 | player.setState(State.fall); 189 | 190 | controller.eventHitEnemy(enemy); 191 | 192 | } else if (player.collisionTimer < 0) { 193 | // Player gets hit. 194 | player.dir = enemy.position.x + enemy.rect.width / 2 < player.position.x + player.rect.width / 2 ? -1 : 1; 195 | float amount = Player.knockbackX * player.dir; 196 | player.velocity.x = -amount; 197 | player.velocity.y += Player.knockbackY; 198 | player.setGrounded(false); 199 | player.hp--; 200 | if (player.hp > 0) { 201 | player.setState(State.fall); 202 | player.collisionTimer = Player.collisionDelay; 203 | 204 | enemy.velocity.x = amount * 1.6f; 205 | enemy.velocity.y += 5f; 206 | enemy.setState(State.fall); 207 | enemy.jumpDelayTimer = MathUtils.random(0, enemy.jumpDelay); 208 | } else { 209 | player.setState(State.death); 210 | player.velocity.y *= 0.5f; 211 | } 212 | enemy.setGrounded(false); 213 | enemy.collisionTimer = Enemy.collisionDelay; 214 | 215 | controller.eventHitPlayer(enemy); 216 | } 217 | } 218 | } 219 | } 220 | // End the game when all enemies are dead and all triggers have occurred. 221 | if (alive == 0 && triggers.size == 0) controller.eventGameOver(true); 222 | } 223 | 224 | void updateBullets (float delta) { 225 | outer: 226 | for (int i = bullets.size - 5; i >= 0; i -= 5) { 227 | float vx = bullets.get(i); 228 | float vy = bullets.get(i + 1); 229 | float x = bullets.get(i + 2); 230 | float y = bullets.get(i + 3); 231 | if (collisionLayer.getCell((int)x, (int)y) != null) { 232 | // Bullet hit map. 233 | controller.eventHitBullet(x, y, vx, vy); 234 | bullets.removeRange(i, i + 4); 235 | continue; 236 | } 237 | if (Math.abs(x - player.position.x) > 25) { 238 | // Bullet traveled too far. 239 | bullets.removeRange(i, i + 4); 240 | continue; 241 | } 242 | for (Enemy enemy : enemies) { 243 | if (enemy.state == State.death) continue; 244 | if (enemy.bigTimer <= 0 && enemy.rect.contains(x, y)) { 245 | // Bullet hit enemy. 246 | bullets.removeRange(i, i + 4); 247 | controller.eventHitBullet(x, y, vx, vy); 248 | controller.eventHitEnemy(enemy); 249 | enemy.collisionTimer = Enemy.collisionDelay; 250 | enemy.hp--; 251 | if (enemy.hp <= 0) { 252 | enemy.state = State.death; 253 | enemy.velocity.y *= 0.5f; 254 | } else 255 | enemy.state = State.fall; 256 | enemy.velocity.x = MathUtils.random(enemy.knockbackX / 2, enemy.knockbackX) 257 | * (player.position.x < enemy.position.x + enemy.rect.width / 2 ? 1 : -1); 258 | enemy.velocity.y += MathUtils.random(enemy.knockbackY / 2, enemy.knockbackY); 259 | continue outer; 260 | } 261 | } 262 | x += vx * delta; 263 | y += vy * delta; 264 | bullets.set(i + 2, x); 265 | bullets.set(i + 3, y); 266 | } 267 | } 268 | 269 | void addBullet (float startX, float startY, float vx, float vy, float angle) { 270 | bullets.add(vx); 271 | bullets.add(vy); 272 | bullets.add(startX); 273 | bullets.add(startY); 274 | bullets.add(angle); 275 | } 276 | 277 | /** Returns rectangles for the tiles within the specified area. */ 278 | Array getCollisionTiles (int startX, int startY, int endX, int endY) { 279 | Pools.freeAll(tiles, true); 280 | tiles.clear(); 281 | for (int y = startY; y <= endY; y++) { 282 | for (int x = startX; x <= endX; x++) { 283 | Cell cell = collisionLayer.getCell(x, y); 284 | if (cell != null) { 285 | Rectangle rect = Pools.obtain(Rectangle.class); 286 | rect.set(x, y, 1, 1); 287 | tiles.add(rect); 288 | } 289 | } 290 | } 291 | return tiles; 292 | } 293 | 294 | float getTimeScale () { 295 | if (player.hp == 0) 296 | return timeScale * Interpolation.pow2In.apply(0, 1, MathUtils.clamp(gameOverTimer / gameOverSlowdown, 0.01f, 1)); 297 | return timeScale; 298 | } 299 | 300 | enum State { 301 | idle, run, jump, death, fall 302 | } 303 | 304 | static class Trigger { 305 | float x; 306 | Array enemies = new Array(); 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /src/com/esotericsoftware/spine/superspineboy/Player.java: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes License Agreement 3 | * Last updated February 20, 2024. Replaces all prior versions. 4 | * 5 | * Copyright (c) 2013-2024, Esoteric Software LLC 6 | * 7 | * Integration of the Spine Runtimes into software or otherwise creating derivative works 8 | * of the Spine Runtimes is permitted under the terms and conditions of Section 2 of the 9 | * Spine Editor License Agreement: 10 | * https://esotericsoftware.com/spine-editor-license 11 | * 12 | * Otherwise, it is permitted to integrate the Spine Runtimes into software or otherwise 13 | * create derivative works of the Spine Runtimes (collectively, "Products"), provided that 14 | * each user of the Products must obtain their own Spine Editor license and redistribution 15 | * of the Products in any form must include this license and copyright notice. 16 | * 17 | * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, 22 | * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SPINE RUNTIMES, 25 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *****************************************************************************/ 27 | 28 | package com.esotericsoftware.spine.superspineboy; 29 | 30 | import static com.esotericsoftware.spine.superspineboy.Model.*; 31 | 32 | /** The model class for the player. */ 33 | class Player extends Character { 34 | static float heightSource = 625, width = 67 * scale, height = 285 * scale; 35 | static float hpStart = 4, hpDuration = 15; 36 | 37 | static float maxVelocityGroundX = 12.5f, maxVelocityAirX = 13.5f; 38 | static float playerJumpVelocity = 22f, jumpDamping = 0.5f, jumpOffsetVelocity = 10, jumpOffsetY = 120 * scale; 39 | static float airJumpTime = 0.1f; 40 | 41 | static float shootDelay = 0.1f, shootOffsetX = 160, shootOffsetY = 11; 42 | static float bulletSpeed = 34, bulletInheritVelocity = 0.4f, burstDuration = 0.18f; 43 | static float kickbackShots = 33, kickbackAngle = 30, kickbackVarianceShots = 11, kickbackVariance = 6, kickback = 1.6f; 44 | 45 | static float knockbackX = 14, knockbackY = 5, collisionDelay = 2.5f, flashTime = 0.07f; 46 | static float headBounceX = 12, headBounceY = 20; 47 | 48 | float shootTimer; 49 | float collisionTimer; 50 | float hpTimer; 51 | 52 | // This is here for convenience, the model should never touch the view. 53 | PlayerView view; 54 | 55 | Player (Model model) { 56 | super(model); 57 | rect.width = width; 58 | rect.height = height; 59 | hp = hpStart; 60 | jumpVelocity = playerJumpVelocity; 61 | } 62 | 63 | void update (float delta) { 64 | stateChanged = false; 65 | 66 | shootTimer -= delta; 67 | 68 | if (hp > 0) { 69 | hpTimer -= delta; 70 | if (hpTimer < 0) { 71 | hpTimer = hpDuration; 72 | if (hp < hpStart) hp++; 73 | } 74 | } 75 | 76 | collisionTimer -= delta; 77 | rect.height = height - collisionOffsetY; 78 | maxVelocityX = isGrounded() ? maxVelocityGroundX : maxVelocityAirX; 79 | super.update(delta); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/com/esotericsoftware/spine/superspineboy/PlayerView.java: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes License Agreement 3 | * Last updated February 20, 2024. Replaces all prior versions. 4 | * 5 | * Copyright (c) 2013-2024, Esoteric Software LLC 6 | * 7 | * Integration of the Spine Runtimes into software or otherwise creating derivative works 8 | * of the Spine Runtimes is permitted under the terms and conditions of Section 2 of the 9 | * Spine Editor License Agreement: 10 | * https://esotericsoftware.com/spine-editor-license 11 | * 12 | * Otherwise, it is permitted to integrate the Spine Runtimes into software or otherwise 13 | * create derivative works of the Spine Runtimes (collectively, "Products"), provided that 14 | * each user of the Products must obtain their own Spine Editor license and redistribution 15 | * of the Products in any form must include this license and copyright notice. 16 | * 17 | * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, 22 | * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SPINE RUNTIMES, 25 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *****************************************************************************/ 27 | 28 | package com.esotericsoftware.spine.superspineboy; 29 | 30 | import static com.esotericsoftware.spine.superspineboy.Model.*; 31 | import static com.esotericsoftware.spine.superspineboy.Player.*; 32 | 33 | import com.badlogic.gdx.Gdx; 34 | import com.badlogic.gdx.math.Interpolation; 35 | import com.badlogic.gdx.math.MathUtils; 36 | import com.badlogic.gdx.math.Vector2; 37 | 38 | import com.esotericsoftware.spine.Animation; 39 | import com.esotericsoftware.spine.AnimationState; 40 | import com.esotericsoftware.spine.AnimationState.AnimationStateAdapter; 41 | import com.esotericsoftware.spine.Bone; 42 | import com.esotericsoftware.spine.Event; 43 | import com.esotericsoftware.spine.EventData; 44 | import com.esotericsoftware.spine.Skeleton; 45 | import com.esotericsoftware.spine.Skeleton.Physics; 46 | import com.esotericsoftware.spine.superspineboy.Assets.SoundEffect; 47 | import com.esotericsoftware.spine.superspineboy.Model.State; 48 | 49 | /** The view class for the player. */ 50 | class PlayerView extends CharacterView { 51 | Player player; 52 | Bone rearUpperArmBone, rearBracerBone, gunBone, headBone, torsoBone, frontUpperArmBone; 53 | Animation shootAnimation, hitAnimation; 54 | boolean canShoot; 55 | float burstShots, burstTimer; 56 | Vector2 temp1 = new Vector2(), temp2 = new Vector2(); 57 | 58 | PlayerView (final View view) { 59 | super(view); 60 | player = view.player; 61 | 62 | skeleton = new Skeleton(view.assets.playerSkeletonData); 63 | 64 | // We'll allow any of the bones or animations to be null in case someone has swapped out spineboy for a different skeleton. 65 | rearUpperArmBone = skeleton.findBone("rear_upper_arm"); 66 | rearBracerBone = skeleton.findBone("rear_bracer"); 67 | gunBone = skeleton.findBone("gun"); 68 | headBone = skeleton.findBone("head"); 69 | torsoBone = skeleton.findBone("torso"); 70 | frontUpperArmBone = skeleton.findBone("front_upper_arm"); 71 | shootAnimation = view.assets.playerSkeletonData.findAnimation("shoot"); 72 | hitAnimation = view.assets.playerSkeletonData.findAnimation("hit"); 73 | 74 | animationState = new AnimationState(view.assets.playerAnimationData); 75 | 76 | // Play footstep sounds. 77 | final EventData footstepEvent = view.assets.playerSkeletonData.findEvent("footstep"); 78 | animationState.addListener(new AnimationStateAdapter() { 79 | public void event (int trackIndex, Event event) { 80 | if (event.getData() == footstepEvent) { 81 | if (event.getInt() == 1) 82 | SoundEffect.footstep1.play(); 83 | else 84 | SoundEffect.footstep2.play(); 85 | } 86 | } 87 | }); 88 | } 89 | 90 | void update (float delta) { 91 | // When not shooting, reset the number of burst shots. 92 | if (!view.touched && burstTimer > 0) { 93 | burstTimer -= delta; 94 | if (burstTimer < 0) burstShots = 0; 95 | } 96 | 97 | // If jump was pressed in the air, jump as soon as grounded. 98 | if (view.jumpPressed && player.isGrounded()) jump(); 99 | 100 | skeleton.setX(player.position.x + width / 2); 101 | skeleton.setY(player.position.y); 102 | 103 | if (!setAnimation(view.assets.playerStates.get(player.state), player.stateChanged)) animationState.update(delta); 104 | animationState.apply(skeleton); 105 | 106 | Vector2 mouse = temp1.set(Gdx.input.getX(), Gdx.input.getY()); 107 | view.viewport.unproject(mouse); 108 | 109 | // Determine if the player can shoot at the mouse position. 110 | canShoot = false; 111 | if (rearUpperArmBone == null || rearBracerBone == null || gunBone == null) 112 | canShoot = true; 113 | else if (player.hp > 0 && !view.ui.hasSplash 114 | && (Math.abs(skeleton.getY() - mouse.y) > 2.7f || Math.abs(skeleton.getX() - mouse.x) > 0.75f)) { 115 | // Store bone rotations from the animation that was applied. 116 | float rearUpperArmRotation = rearUpperArmBone.getRotation(); 117 | float rearBracerRotation = rearBracerBone.getRotation(); 118 | float gunRotation = gunBone.getRotation(); 119 | // Straighten the arm and don't flipX, so the arm can more easily point at the mouse. 120 | rearUpperArmBone.setRotation(0); 121 | float shootRotation = 11; 122 | if (animationState.getCurrent(1) == null) { 123 | rearBracerBone.setRotation(0); 124 | gunBone.setRotation(0); 125 | } else 126 | shootRotation += 25; // Use different rotation when shoot animation was applied. 127 | skeleton.setScaleX(1); 128 | skeleton.updateWorldTransform(Physics.none); 129 | 130 | // Compute the arm's angle to the mouse, flipping it based on the direction the player faces. 131 | Vector2 bonePosition = temp2.set(rearUpperArmBone.getWorldX(), rearUpperArmBone.getWorldY()); 132 | float angle = bonePosition.sub(mouse).angle(); 133 | float behind = (angle < 90 || angle > 270) ? -1 : 1; 134 | if (behind == -1) angle = -angle; 135 | if (player.state == State.idle || (view.touched && (player.state == State.jump || player.state == State.fall))) 136 | player.dir = behind; 137 | if (behind != player.dir) angle = -angle; 138 | if (player.state != State.idle && behind != player.dir) { 139 | // Don't allow the player to shoot behind themselves unless idle. Use the rotations stored earlier from the animation. 140 | rearBracerBone.setRotation(rearBracerRotation); 141 | rearUpperArmBone.setRotation(rearUpperArmRotation); 142 | gunBone.setRotation(gunRotation); 143 | } else { 144 | if (behind == 1) angle += 180; 145 | // Adjust the angle upward based on the number of shots in the current burst. 146 | angle += kickbackAngle * Math.min(1, burstShots / kickbackShots) * (burstTimer / burstDuration); 147 | float gunArmAngle = angle - shootRotation; 148 | // Compute the head, torso and front arm angles so the player looks up or down. 149 | float headAngle; 150 | if (player.dir == -1) { 151 | angle += 360; 152 | if (angle < 180) 153 | headAngle = 25 * Interpolation.pow2In.apply(Math.min(1, angle / 50f)); 154 | else 155 | headAngle = -15 * Interpolation.pow2In.apply(1 - Math.max(0, angle - 310) / 50f); 156 | } else { 157 | if (angle < 360) 158 | headAngle = -15 * Interpolation.pow2In.apply(1 - Math.max(0, (angle - 310) / 50f)); 159 | else 160 | headAngle = 25 * Interpolation.pow2In.apply(1 - Math.max(0, (410 - angle) / 50f)); 161 | } 162 | float torsoAngle = headAngle * 0.75f; 163 | if (headBone != null) headBone.setRotation(headBone.getRotation() + headAngle); 164 | if (torsoBone != null) torsoBone.setRotation(torsoBone.getRotation() + torsoAngle); 165 | if (frontUpperArmBone != null) frontUpperArmBone.setRotation(frontUpperArmBone.getRotation() - headAngle * 1.4f); 166 | rearUpperArmBone.setRotation(gunArmAngle - torsoAngle - rearUpperArmBone.getWorldRotationX()); 167 | canShoot = true; 168 | } 169 | } 170 | 171 | skeleton.setScaleX(player.dir); 172 | skeleton.updateWorldTransform(null); 173 | } 174 | 175 | void jump () { 176 | view.jumpPressed = false; 177 | player.jump(); 178 | setAnimation(view.assets.playerStates.get(State.jump), true); 179 | } 180 | 181 | void shoot () { 182 | if (!canShoot || player.shootTimer >= 0) return; 183 | player.shootTimer = shootDelay; 184 | burstTimer = burstDuration; 185 | 186 | // Compute the position and velocity to spawn a new bullet. 187 | float x = 0, y = 0; 188 | if (rearUpperArmBone != null && rearBracerBone != null && gunBone != null) { 189 | x += rearUpperArmBone.getWorldX(); 190 | y += rearUpperArmBone.getWorldY(); 191 | } else { 192 | x += width / 2; 193 | y += height / 2; 194 | } 195 | float mouseX = Gdx.input.getX(), mouseY = Gdx.input.getY(); 196 | 197 | float angle = view.viewport.unproject(temp1.set(mouseX, mouseY)).sub(x, y).angle(); 198 | angle += kickbackAngle * Math.min(1, burstShots / kickbackShots) * player.dir; 199 | float variance = kickbackVariance * Math.min(1, burstShots / kickbackVarianceShots); 200 | angle += MathUtils.random(-variance, variance); 201 | 202 | float cos = MathUtils.cosDeg(angle), sin = MathUtils.sinDeg(angle); 203 | float vx = cos * bulletSpeed + player.velocity.x * bulletInheritVelocity; 204 | float vy = sin * bulletSpeed + player.velocity.y * bulletInheritVelocity; 205 | if (rearUpperArmBone != null && rearBracerBone != null && gunBone != null) { 206 | x = gunBone.getWorldX(); 207 | y = gunBone.getWorldY() + shootOffsetY * scale; 208 | x += cos * shootOffsetX * scale; 209 | y += sin * shootOffsetX * scale; 210 | } 211 | model.addBullet(x, y, vx, vy, temp1.set(vx, vy).angle()); 212 | if (shootAnimation != null) animationState.setAnimation(1, shootAnimation, false); 213 | 214 | view.camera.position.sub(view.shakeX, view.shakeY, 0); 215 | view.shakeX += View.cameraShake * (MathUtils.randomBoolean() ? 1 : -1); 216 | view.shakeY += View.cameraShake * (MathUtils.randomBoolean() ? 1 : -1); 217 | view.camera.position.add(view.shakeX, view.shakeY, 0); 218 | 219 | player.velocity.x -= kickback * player.dir; 220 | SoundEffect.shoot.play(); 221 | 222 | burstShots = Math.min(kickbackShots, burstShots + 1); 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /src/com/esotericsoftware/spine/superspineboy/SuperSpineboy.java: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes License Agreement 3 | * Last updated February 20, 2024. Replaces all prior versions. 4 | * 5 | * Copyright (c) 2013-2024, Esoteric Software LLC 6 | * 7 | * Integration of the Spine Runtimes into software or otherwise creating derivative works 8 | * of the Spine Runtimes is permitted under the terms and conditions of Section 2 of the 9 | * Spine Editor License Agreement: 10 | * https://esotericsoftware.com/spine-editor-license 11 | * 12 | * Otherwise, it is permitted to integrate the Spine Runtimes into software or otherwise 13 | * create derivative works of the Spine Runtimes (collectively, "Products"), provided that 14 | * each user of the Products must obtain their own Spine Editor license and redistribution 15 | * of the Products in any form must include this license and copyright notice. 16 | * 17 | * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, 22 | * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SPINE RUNTIMES, 25 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *****************************************************************************/ 27 | 28 | package com.esotericsoftware.spine.superspineboy; 29 | 30 | import com.badlogic.gdx.ApplicationAdapter; 31 | import com.badlogic.gdx.Gdx; 32 | import com.badlogic.gdx.backends.lwjgl.LwjglApplication; 33 | import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; 34 | import com.badlogic.gdx.math.Vector2; 35 | 36 | import com.esotericsoftware.spine.AnimationState.TrackEntry; 37 | import com.esotericsoftware.spine.superspineboy.Assets.SoundEffect; 38 | 39 | /** The controller class for the game. It knows about both the model and view and provides a way for the view to know about events 40 | * that occur in the model. */ 41 | class SuperSpineboy extends ApplicationAdapter { 42 | static Vector2 temp = new Vector2(); 43 | 44 | View view; 45 | Model model; 46 | 47 | public void create () { 48 | model = new Model(this); 49 | view = new View(model); 50 | } 51 | 52 | public void render () { 53 | float delta = Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f) * model.getTimeScale(); 54 | if (delta > 0) { 55 | model.update(delta); 56 | view.update(delta); 57 | } 58 | view.render(); 59 | } 60 | 61 | public void resize (int width, int height) { 62 | view.resize(width, height); 63 | } 64 | 65 | void restart () { 66 | model.restart(); 67 | view.restart(); 68 | } 69 | 70 | void eventHitPlayer (Enemy enemy) { 71 | SoundEffect.hurtPlayer.play(); 72 | if (view.player.hp > 0 && view.player.view.hitAnimation != null) { 73 | TrackEntry entry = view.player.view.animationState.setAnimation(1, view.player.view.hitAnimation, false); 74 | entry.setTrackEnd(view.player.view.hitAnimation.getDuration()); 75 | } 76 | } 77 | 78 | void eventHitEnemy (Enemy enemy) { 79 | SoundEffect.hurtAlien.play(); 80 | if (enemy.view.hitAnimation != null) { 81 | TrackEntry entry = enemy.view.animationState.setAnimation(1, enemy.view.hitAnimation, false); 82 | entry.setTrackEnd(enemy.view.hitAnimation.getDuration()); 83 | } 84 | } 85 | 86 | void eventHitBullet (float x, float y, float vx, float vy) { 87 | Vector2 offset = temp.set(vx, vy).nor().scl(15 * Model.scale); 88 | view.hits.add(View.bulletHitTime); 89 | view.hits.add(x + offset.x); 90 | view.hits.add(y + offset.y); 91 | view.hits.add(temp.angle() + 90); 92 | SoundEffect.hit.play(); 93 | } 94 | 95 | void eventGameOver (boolean win) { 96 | if (!view.ui.splashTable.hasParent()) { 97 | view.ui.showSplash(view.assets.gameOverRegion, win ? view.assets.youWinRegion : view.assets.youLoseRegion); 98 | view.ui.inputTimer = win ? 5 : 1; 99 | } 100 | view.jumpPressed = false; 101 | view.leftPressed = false; 102 | view.rightPressed = false; 103 | } 104 | 105 | public static void main (String[] args) throws Exception { 106 | LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); 107 | config.title = "Super Spineboy"; 108 | config.width = 800; 109 | config.height = 450; 110 | new LwjglApplication(new SuperSpineboy(), config); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/com/esotericsoftware/spine/superspineboy/UI.java: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes License Agreement 3 | * Last updated February 20, 2024. Replaces all prior versions. 4 | * 5 | * Copyright (c) 2013-2024, Esoteric Software LLC 6 | * 7 | * Integration of the Spine Runtimes into software or otherwise creating derivative works 8 | * of the Spine Runtimes is permitted under the terms and conditions of Section 2 of the 9 | * Spine Editor License Agreement: 10 | * https://esotericsoftware.com/spine-editor-license 11 | * 12 | * Otherwise, it is permitted to integrate the Spine Runtimes into software or otherwise 13 | * create derivative works of the Spine Runtimes (collectively, "Products"), provided that 14 | * each user of the Products must obtain their own Spine Editor license and redistribution 15 | * of the Products in any form must include this license and copyright notice. 16 | * 17 | * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY EXPRESS OR IMPLIED 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR 20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, 22 | * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SPINE RUNTIMES, 25 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *****************************************************************************/ 27 | 28 | package com.esotericsoftware.spine.superspineboy; 29 | 30 | import static com.badlogic.gdx.math.Interpolation.*; 31 | import static com.badlogic.gdx.scenes.scene2d.actions.Actions.*; 32 | import static com.esotericsoftware.spine.superspineboy.Model.*; 33 | import static com.esotericsoftware.spine.superspineboy.View.*; 34 | 35 | import com.badlogic.gdx.Gdx; 36 | import com.badlogic.gdx.Graphics.DisplayMode; 37 | import com.badlogic.gdx.Input.Keys; 38 | import com.badlogic.gdx.InputAdapter; 39 | import com.badlogic.gdx.graphics.Color; 40 | import com.badlogic.gdx.graphics.Pixmap; 41 | import com.badlogic.gdx.graphics.Pixmap.Format; 42 | import com.badlogic.gdx.graphics.Texture; 43 | import com.badlogic.gdx.graphics.g2d.Batch; 44 | import com.badlogic.gdx.graphics.g2d.BitmapFont; 45 | import com.badlogic.gdx.graphics.g2d.SpriteCache; 46 | import com.badlogic.gdx.graphics.g2d.TextureRegion; 47 | import com.badlogic.gdx.graphics.glutils.ShapeRenderer; 48 | import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; 49 | import com.badlogic.gdx.math.Rectangle; 50 | import com.badlogic.gdx.math.Vector2; 51 | import com.badlogic.gdx.scenes.scene2d.Actor; 52 | import com.badlogic.gdx.scenes.scene2d.InputEvent; 53 | import com.badlogic.gdx.scenes.scene2d.InputListener; 54 | import com.badlogic.gdx.scenes.scene2d.Stage; 55 | import com.badlogic.gdx.scenes.scene2d.Touchable; 56 | import com.badlogic.gdx.scenes.scene2d.ui.ButtonGroup; 57 | import com.badlogic.gdx.scenes.scene2d.ui.Image; 58 | import com.badlogic.gdx.scenes.scene2d.ui.Label; 59 | import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle; 60 | import com.badlogic.gdx.scenes.scene2d.ui.ProgressBar; 61 | import com.badlogic.gdx.scenes.scene2d.ui.ProgressBar.ProgressBarStyle; 62 | import com.badlogic.gdx.scenes.scene2d.ui.Skin; 63 | import com.badlogic.gdx.scenes.scene2d.ui.Table; 64 | import com.badlogic.gdx.scenes.scene2d.ui.TextButton; 65 | import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle; 66 | import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; 67 | import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; 68 | import com.badlogic.gdx.scenes.scene2d.utils.UIUtils; 69 | import com.badlogic.gdx.utils.FloatArray; 70 | import com.badlogic.gdx.utils.Scaling; 71 | import com.badlogic.gdx.utils.viewport.ScreenViewport; 72 | import com.esotericsoftware.spine.SkeletonRendererDebug; 73 | 74 | /** The user interface displayed on top of the game (menu, health bar, splash screens). */ 75 | class UI extends InputAdapter { 76 | static final Color gray = new Color(0.15f, 0.15f, 0.15f, 1); 77 | 78 | View view; 79 | Model model; 80 | 81 | ShapeRenderer shapes; 82 | SkeletonRendererDebug skeletonRendererDebug; 83 | Stage stage; 84 | Skin skin; 85 | Label fpsLabel, bindsLabel; 86 | TextButton debugButton, zoomButton, bgButton; 87 | TextButton speed200Button, speed150Button, speed100Button, speed33Button, speed15Button, speed3Button, pauseButton; 88 | Table splashTable; 89 | Image splashImage, splashTextImage; 90 | ProgressBar healthBar; 91 | TextButton fullscreenButton, restartButton, menuButton; 92 | Table menu; 93 | Vector2 temp = new Vector2(); 94 | 95 | int windowWidth, windowHeight; 96 | float inputTimer; 97 | boolean hasSplash; 98 | 99 | UI (final View view) { 100 | this.view = view; 101 | this.model = view.model; 102 | 103 | shapes = new ShapeRenderer(); 104 | 105 | skeletonRendererDebug = new SkeletonRendererDebug(shapes); 106 | skeletonRendererDebug.setScale(scale); 107 | // skeletonRendererDebug.setPremultipliedAlpha(true); 108 | 109 | stage = new Stage(new ScreenViewport()); 110 | loadSkin(); 111 | 112 | create(); 113 | layout(); 114 | events(); 115 | 116 | showSplash(view.assets.titleRegion, view.assets.startRegion); 117 | } 118 | 119 | private void create () { 120 | speed200Button = speedButton(2f); 121 | speed150Button = speedButton(1.5f); 122 | speed100Button = speedButton(1); 123 | speed33Button = speedButton(0.33f); 124 | speed15Button = speedButton(0.15f); 125 | speed3Button = speedButton(0.03f); 126 | pauseButton = speedButton(0); 127 | pauseButton.setText("Pause"); 128 | new ButtonGroup(speed200Button, speed150Button, speed100Button, speed33Button, speed15Button, speed3Button, pauseButton); 129 | speed100Button.setChecked(true); 130 | 131 | healthBar = new ProgressBar(0, Player.hpStart, 1, false, skin); 132 | healthBar.setAnimateDuration(0.3f); 133 | healthBar.setAnimateInterpolation(fade); 134 | fpsLabel = new Label("", skin); 135 | bindsLabel = new Label("", skin); 136 | debugButton = button("Debug", true); 137 | zoomButton = button("Zoom", true); 138 | bgButton = button("Background", true); 139 | bgButton.setChecked(true); 140 | 141 | fullscreenButton = button("Fullscreen", true); 142 | 143 | menuButton = button("Menu", true); 144 | menuButton.getColor().a = 0.3f; 145 | 146 | splashImage = new Image(); 147 | splashImage.setScaling(Scaling.fit); 148 | 149 | splashTextImage = new Image(); 150 | splashTextImage.addAction(forever(sequence(fadeOut(0.4f, pow2In), fadeIn(0.4f, pow2Out)))); 151 | } 152 | 153 | private void layout () { 154 | Table buttons = new Table(); 155 | buttons.defaults().uniformX().fillX(); 156 | buttons.add(speed200Button).row(); 157 | buttons.add(speed150Button).row(); 158 | buttons.add(speed100Button).row(); 159 | buttons.add(speed33Button).row(); 160 | buttons.add(speed15Button).row(); 161 | buttons.add(speed3Button).row(); 162 | buttons.add(pauseButton).row(); 163 | buttons.defaults().padTop(5); 164 | buttons.add(debugButton).row(); 165 | buttons.add(zoomButton).row(); 166 | buttons.add(bgButton).row(); 167 | buttons.add(fullscreenButton).row(); 168 | buttons.add(restartButton).row(); 169 | 170 | menu = new Table(skin); 171 | menu.defaults().space(5); 172 | menu.add("FPS:"); 173 | menu.add(fpsLabel).expandX().left().row(); 174 | menu.add("Binds:"); 175 | menu.add(bindsLabel).left().row(); 176 | menu.add(buttons).colspan(2).left(); 177 | menu.setVisible(false); 178 | 179 | Table root = new Table(skin); 180 | stage.addActor(root); 181 | root.top().left().pad(5).defaults().space(5); 182 | root.setFillParent(true); 183 | root.add(menuButton).fillX(); 184 | root.add(healthBar).height(10).fillY().expandX().right().top().row(); 185 | root.add(menu); 186 | 187 | splashTable = new Table(skin); 188 | splashTable.setFillParent(true); 189 | splashTable.add(splashImage).fillX().row(); 190 | splashTable.add(splashTextImage); 191 | splashTable.setTouchable(Touchable.enabled); 192 | } 193 | 194 | private void events () { 195 | menuButton.addListener(new ChangeListener() { 196 | public void changed (ChangeEvent event, Actor actor) { 197 | menu.clearActions(); 198 | menu.getColor().a = menu.isVisible() ? 1 : 0; 199 | if (menu.isVisible()) 200 | menu.addAction(sequence(alpha(0, 0.5f, fade), hide())); 201 | else 202 | menu.addAction(sequence(show(), alpha(1, 0.5f, fade))); 203 | menuButton.getColor().a = menu.isVisible() ? 0.3f : 1; 204 | } 205 | }); 206 | 207 | fullscreenButton.addListener(new ChangeListener() { 208 | public void changed (ChangeEvent event, Actor actor) { 209 | toggleFullscreen(); 210 | } 211 | }); 212 | 213 | restartButton = button("Restart", false); 214 | restartButton.addListener(new ChangeListener() { 215 | public void changed (ChangeEvent event, Actor actor) { 216 | model.controller.restart(); 217 | } 218 | }); 219 | 220 | splashTable.addListener(new InputListener() { 221 | public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) { 222 | if (hasSplash && inputTimer < 0) { 223 | model.controller.restart(); 224 | splashTable.clearActions(); 225 | splashTable.getColor().a = 1; 226 | splashTable.addAction(sequence(fadeOut(1, fade), removeActor())); 227 | hasSplash = false; 228 | return true; 229 | } 230 | return false; 231 | } 232 | }); 233 | } 234 | 235 | void loadSkin () { 236 | skin = new Skin(); 237 | skin.add("default", new BitmapFont()); 238 | 239 | Pixmap pixmap = new Pixmap(1, 1, Format.RGBA8888); 240 | pixmap.setColor(Color.WHITE); 241 | pixmap.fill(); 242 | skin.add("white", new Texture(pixmap)); 243 | 244 | TextButtonStyle textButtonStyle = new TextButtonStyle(); 245 | textButtonStyle.up = skin.newDrawable("white", Color.DARK_GRAY); 246 | textButtonStyle.down = skin.newDrawable("white", new Color(0x416ba1ff)); 247 | textButtonStyle.over = skin.newDrawable("white", Color.GRAY); 248 | textButtonStyle.font = skin.getFont("default"); 249 | skin.add("default", textButtonStyle); 250 | 251 | textButtonStyle = new TextButtonStyle(textButtonStyle); 252 | textButtonStyle.checked = skin.newDrawable("white", new Color(0x5287ccff)); 253 | skin.add("toggle", textButtonStyle); 254 | 255 | LabelStyle labelStyle = new LabelStyle(); 256 | labelStyle.font = skin.getFont("default"); 257 | skin.add("default", labelStyle); 258 | 259 | ProgressBarStyle progressBarStyle = new ProgressBarStyle(); 260 | progressBarStyle.background = skin.newDrawable("white", new Color(0.25f, 0.25f, 0.25f, 0.66f)); 261 | progressBarStyle.background.setMinHeight(15); 262 | progressBarStyle.knobBefore = skin.newDrawable("white", Color.CLEAR); 263 | progressBarStyle.knobBefore.setMinHeight(15); 264 | progressBarStyle.knobAfter = skin.newDrawable("white", new Color(1, 0, 0, 0.66f)); 265 | progressBarStyle.knobAfter.setMinHeight(15); 266 | skin.add("default-horizontal", progressBarStyle); 267 | } 268 | 269 | TextButton speedButton (final float speed) { 270 | final TextButton button = button((int)(speed * 100) + "%", true); 271 | button.addListener(new ChangeListener() { 272 | public void changed (ChangeEvent event, Actor actor) { 273 | if (button.isChecked()) model.timeScale = speed; 274 | } 275 | }); 276 | return button; 277 | } 278 | 279 | TextButton button (String text, boolean toggle) { 280 | TextButton button = new TextButton(text, skin, toggle ? "toggle" : "default"); 281 | button.pad(2, 12, 2, 12); 282 | return button; 283 | } 284 | 285 | void render () { 286 | float delta = Gdx.graphics.getDeltaTime(); 287 | inputTimer -= delta; 288 | 289 | float zoom = zoomButton.isChecked() ? cameraZoom : 1; 290 | if (view.zoom != zoom) { 291 | if (view.zoom < zoom) 292 | view.zoom = Math.min(zoom, view.zoom + cameraZoomSpeed * delta); 293 | else 294 | view.zoom = Math.max(zoom, view.zoom - cameraZoomSpeed * delta); 295 | view.viewport.setMinWorldWidth(cameraMinWidth * view.zoom); 296 | view.viewport.setMinWorldHeight(cameraHeight * view.zoom); 297 | view.viewport.setMaxWorldWidth(cameraMaxWidth * view.zoom); 298 | view.viewport.setMaxWorldHeight(cameraHeight * view.zoom); 299 | view.viewport.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); 300 | } 301 | 302 | if (!bgButton.isChecked()) { 303 | shapes.setTransformMatrix(view.batch.getTransformMatrix()); 304 | shapes.setProjectionMatrix(view.batch.getProjectionMatrix()); 305 | shapes.setColor(gray); 306 | shapes.begin(ShapeType.Filled); 307 | float w = view.viewport.getWorldWidth(), h = view.viewport.getWorldHeight(); 308 | int x = (int)(view.camera.position.x - w / 2), y = (int)(view.camera.position.y - h / 2); 309 | for (Rectangle rect : model.getCollisionTiles(x, y, x + (int)(w + 0.5f), y + (int)(h + 0.5f))) { 310 | shapes.rect(rect.x, rect.y, rect.width, rect.height); 311 | } 312 | shapes.end(); 313 | } 314 | 315 | healthBar.setValue(Player.hpStart - model.player.hp); 316 | 317 | SpriteCache spriteCache = view.mapRenderer.getSpriteCache(); 318 | int renderCalls = view.batch.totalRenderCalls + spriteCache.totalRenderCalls; 319 | view.batch.totalRenderCalls = 0; 320 | spriteCache.totalRenderCalls = 0; 321 | fpsLabel.setText(Integer.toString(Gdx.graphics.getFramesPerSecond())); 322 | bindsLabel.setText(Integer.toString(renderCalls)); 323 | 324 | if (!hasSplash && debugButton.isChecked()) { 325 | shapes.setTransformMatrix(view.batch.getTransformMatrix()); 326 | shapes.setProjectionMatrix(view.batch.getProjectionMatrix()); 327 | shapes.begin(ShapeType.Line); 328 | 329 | shapes.setColor(Color.GREEN); 330 | 331 | FloatArray bullets = model.bullets; 332 | for (int i = bullets.size - 5; i >= 0; i -= 5) { 333 | float x = bullets.get(i + 2); 334 | float y = bullets.get(i + 3); 335 | shapes.x(x, y, 10 * scale); 336 | } 337 | 338 | FloatArray hits = view.hits; 339 | for (int i = hits.size - 4; i >= 0; i -= 4) { 340 | float x = hits.get(i + 1); 341 | float y = hits.get(i + 2); 342 | shapes.x(x, y, 10 * scale); 343 | } 344 | 345 | for (Enemy enemy : model.enemies) { 346 | Rectangle rect = enemy.rect; 347 | shapes.rect(rect.x, rect.y, rect.width, rect.height); 348 | } 349 | 350 | Rectangle rect = model.player.rect; 351 | shapes.rect(rect.x, rect.y, rect.width, rect.height); 352 | 353 | shapes.end(); 354 | 355 | skeletonRendererDebug.draw(model.player.view.skeleton); 356 | for (Enemy enemy : model.enemies) { 357 | skeletonRendererDebug.draw(enemy.view.skeleton); 358 | } 359 | } 360 | 361 | stage.act(); 362 | stage.getViewport().apply(true); 363 | stage.draw(); 364 | 365 | Batch batch = stage.getBatch(); 366 | batch.setColor(Color.WHITE); 367 | batch.begin(); 368 | Vector2 cursor = stage.screenToStageCoordinates(temp.set(Gdx.input.getX(), Gdx.input.getY())); 369 | TextureRegion crosshair = view.assets.crosshair; 370 | batch.draw(crosshair, cursor.x - crosshair.getRegionWidth() / 2, cursor.y - crosshair.getRegionHeight() / 2 + 2); 371 | batch.end(); 372 | } 373 | 374 | void resize (int width, int height) { 375 | stage.getViewport().update(width, height, true); 376 | } 377 | 378 | void toggleFullscreen () { 379 | if (Gdx.graphics.isFullscreen()) 380 | Gdx.graphics.setWindowedMode(windowWidth, windowHeight); 381 | else { 382 | windowWidth = Gdx.graphics.getWidth(); 383 | windowHeight = Gdx.graphics.getHeight(); 384 | Gdx.graphics.setFullscreenMode(Gdx.graphics.getDisplayMode()); 385 | } 386 | } 387 | 388 | void showSplash (TextureRegion splash, TextureRegion text) { 389 | splashImage.setDrawable(new TextureRegionDrawable(splash)); 390 | splashTextImage.setDrawable(new TextureRegionDrawable(text)); 391 | stage.addActor(splashTable); 392 | splashTable.clearActions(); 393 | splashTable.getColor().a = 0; 394 | splashTable.addAction(fadeIn(1)); 395 | hasSplash = true; 396 | } 397 | 398 | public boolean keyDown (int keycode) { 399 | switch (keycode) { 400 | case Keys.NUM_6: 401 | speed200Button.toggle(); 402 | return true; 403 | case Keys.NUM_5: 404 | speed150Button.toggle(); 405 | return true; 406 | case Keys.NUM_4: 407 | speed100Button.toggle(); 408 | return true; 409 | case Keys.NUM_3: 410 | speed33Button.toggle(); 411 | return true; 412 | case Keys.NUM_2: 413 | speed15Button.toggle(); 414 | return true; 415 | case Keys.NUM_1: 416 | speed3Button.toggle(); 417 | return true; 418 | case Keys.P: 419 | case Keys.GRAVE: 420 | pauseButton.toggle(); 421 | return true; 422 | case Keys.B: 423 | bgButton.toggle(); 424 | return true; 425 | case Keys.Z: 426 | zoomButton.toggle(); 427 | return true; 428 | case Keys.I: 429 | debugButton.toggle(); 430 | return true; 431 | case Keys.T: 432 | view.assets.dispose(); 433 | Texture.invalidateAllTextures(Gdx.app); 434 | view.assets = new Assets(); 435 | return true; 436 | case Keys.ESCAPE: 437 | if (Gdx.graphics.isFullscreen()) 438 | Gdx.graphics.setWindowedMode(windowWidth, windowHeight); 439 | else 440 | System.exit(0); 441 | return true; 442 | case Keys.ENTER: 443 | if (UIUtils.alt()) toggleFullscreen(); 444 | return true; 445 | case Keys.O: 446 | showSplash(view.assets.titleRegion, view.assets.startRegion); 447 | return true; 448 | } 449 | return hasSplash; 450 | } 451 | 452 | public boolean keyUp (int keycode) { 453 | return hasSplash; 454 | } 455 | } 456 | -------------------------------------------------------------------------------- /src/com/esotericsoftware/spine/superspineboy/View.java: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Spine Runtimes Software License 3 | * Version 2.1 4 | * 5 | * Copyright (c) 2013, Esoteric Software 6 | * All rights reserved. 7 | * 8 | * You are granted a perpetual, non-exclusive, non-sublicensable and 9 | * non-transferable license to install, execute and perform the Spine Runtimes 10 | * Software (the "Software") solely for internal use. Without the written 11 | * permission of Esoteric Software (typically granted by licensing Spine), you 12 | * may not (a) modify, translate, adapt or otherwise create derivative works, 13 | * improvements of the Software or develop new applications using the Software 14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright, 15 | * trademark, patent or other intellectual property or proprietary rights notices 16 | * on or in the Software, including any copy thereof. Redistributions in binary 17 | * or source form must include this license and terms. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | *****************************************************************************/ 30 | 31 | package com.esotericsoftware.spine.superspineboy; 32 | 33 | import static com.esotericsoftware.spine.superspineboy.Model.*; 34 | import static com.esotericsoftware.spine.superspineboy.Player.*; 35 | 36 | import com.esotericsoftware.spine.Animation; 37 | import com.esotericsoftware.spine.SkeletonRenderer; 38 | import com.esotericsoftware.spine.superspineboy.Model.State; 39 | import com.esotericsoftware.spine.utils.TwoColorPolygonBatch; 40 | import com.badlogic.gdx.Gdx; 41 | import com.badlogic.gdx.Input.Keys; 42 | import com.badlogic.gdx.InputAdapter; 43 | import com.badlogic.gdx.InputMultiplexer; 44 | import com.badlogic.gdx.graphics.Color; 45 | import com.badlogic.gdx.graphics.GL20; 46 | import com.badlogic.gdx.graphics.OrthographicCamera; 47 | import com.badlogic.gdx.graphics.g2d.SpriteBatch; 48 | import com.badlogic.gdx.graphics.g2d.TextureRegion; 49 | import com.badlogic.gdx.maps.tiled.renderers.OrthoCachedTiledMapRenderer; 50 | import com.badlogic.gdx.math.MathUtils; 51 | import com.badlogic.gdx.math.Vector2; 52 | import com.badlogic.gdx.utils.FloatArray; 53 | import com.badlogic.gdx.utils.ObjectFloatMap; 54 | import com.badlogic.gdx.utils.viewport.ExtendViewport; 55 | 56 | /** The core of the view logic. The view knows about the model and manages everything needed to draw to the screen. */ 57 | class View extends InputAdapter { 58 | static float bulletHitTime = 0.2f, bulletHitOffset = 50 * scale; 59 | 60 | static float cameraMinWidth = 16, cameraMaxWidth = 28, cameraHeight = 16, cameraZoom = 0.4f, cameraZoomSpeed = 0.5f; 61 | static float cameraBottom = 2, cameraTop = 7, cameraMinX = 1; 62 | static float cameraLookahead = 0.75f, cameraLookaheadSpeed = 8f, cameraLookaheadSpeedSlow = 3f; 63 | static float cameraSpeed = 5f, cameraShake = 6 * scale; 64 | 65 | static int[] mapLayersOpaque1 = {1}; 66 | static int[] mapLayersBackground2 = {2, 3, 4, 5, 6}; 67 | static int[] mapLayersOpaque3 = {10}; 68 | static int[] mapForegroundLayers4 = {7, 8,}; 69 | static int[] mapForegroundLayers5 = {11}; 70 | 71 | Model model; 72 | Player player; 73 | OrthographicCamera camera; 74 | ExtendViewport viewport; 75 | TwoColorPolygonBatch batch; 76 | SkeletonRenderer skeletonRenderer; 77 | OrthoCachedTiledMapRenderer mapRenderer; 78 | Assets assets; 79 | UI ui; 80 | 81 | float shakeX, shakeY, lookahead, zoom = 1; 82 | FloatArray hits = new FloatArray(); 83 | boolean touched, jumpPressed, leftPressed, rightPressed; 84 | 85 | View (Model model) { 86 | this.model = model; 87 | 88 | mapRenderer = new OrthoCachedTiledMapRenderer(model.map, scale, 3000); 89 | mapRenderer.setOverCache(0.6f); 90 | mapRenderer.setMaxTileSize(512, 512); 91 | 92 | batch = new TwoColorPolygonBatch(); 93 | camera = new OrthographicCamera(); 94 | viewport = new ExtendViewport(cameraMinWidth, cameraHeight, cameraMaxWidth, cameraHeight, camera); 95 | 96 | skeletonRenderer = new SkeletonRenderer(); 97 | skeletonRenderer.setPremultipliedAlpha(true); 98 | 99 | assets = new Assets(); 100 | 101 | ui = new UI(this); 102 | 103 | Gdx.input.setInputProcessor(new InputMultiplexer(ui, ui.stage, this)); 104 | 105 | restart(); 106 | } 107 | 108 | void restart () { 109 | player = model.player; 110 | player.view = new PlayerView(this); 111 | lookahead = 0; 112 | touched = false; 113 | hits.clear(); 114 | } 115 | 116 | void update (float delta) { 117 | // Update the hit marker images. 118 | for (int i = hits.size - 4; i >= 0; i -= 4) { 119 | float time = hits.get(i) - delta; 120 | if (time < 0) 121 | hits.removeRange(i, i + 3); 122 | else 123 | hits.set(i, time); 124 | } 125 | 126 | updateInput(delta); 127 | updateCamera(delta); 128 | 129 | player.view.update(delta); 130 | 131 | for (Enemy enemy : model.enemies) { 132 | if (enemy.view == null) enemy.view = new EnemyView(this, enemy); 133 | enemy.view.update(delta); 134 | } 135 | } 136 | 137 | void updateInput (float delta) { 138 | if (player.hp == 0) return; 139 | 140 | if (leftPressed) 141 | player.moveLeft(delta); 142 | else if (rightPressed) 143 | player.moveRight(delta); 144 | else if (player.state == State.run) // 145 | player.setState(State.idle); 146 | 147 | if (touched) player.view.shoot(); 148 | } 149 | 150 | void updateCamera (float delta) { 151 | if (player.hp > 0) { 152 | // Reduce camera lookahead based on distance of enemies behind the player. 153 | float enemyBehindDistance = 0; 154 | for (Enemy enemy : model.enemies) { 155 | float dist = enemy.position.x - player.position.x; 156 | if (enemy.hp > 0 && Math.signum(dist) == -player.dir) { 157 | dist = Math.abs(dist); 158 | enemyBehindDistance = enemyBehindDistance == 0 ? dist : Math.min(enemyBehindDistance, dist); 159 | } 160 | } 161 | float lookaheadDist = cameraLookahead * viewport.getWorldWidth() / 2 * (1 - Math.min(1, enemyBehindDistance / 22)); 162 | float lookaheadDiff = player.position.x + lookaheadDist * player.dir - camera.position.x; 163 | float lookaheadAdjust = (enemyBehindDistance > 0 ? cameraLookaheadSpeedSlow : cameraLookaheadSpeed) * delta; 164 | if (Math.abs(lookahead - lookaheadDiff) > 1) { 165 | if (lookahead < lookaheadDiff) 166 | lookahead = Math.min(lookaheadDist, lookahead + lookaheadAdjust); 167 | else if (lookahead > lookaheadDiff) // 168 | lookahead = Math.max(-lookaheadDist, lookahead - lookaheadAdjust); 169 | } 170 | if (player.position.x + lookahead < cameraMinX) lookahead = cameraLookahead; 171 | } 172 | 173 | // Move camera to the player position over time, adjusting for lookahead. 174 | float minX = player.position.x + lookahead, maxX = player.position.x + lookahead; 175 | if (camera.position.x < minX) { 176 | camera.position.x += (minX - camera.position.x) * cameraSpeed * delta; 177 | if (camera.position.x > minX) camera.position.x = minX; 178 | if (Math.abs(camera.position.x - minX) < 0.1f) camera.position.x = minX; 179 | } else if (camera.position.x > maxX) { 180 | camera.position.x += (maxX - camera.position.x) * cameraSpeed * delta; 181 | if (camera.position.x < maxX) camera.position.x = maxX; 182 | if (Math.abs(camera.position.x - maxX) < 0.1f) camera.position.x = maxX; 183 | } 184 | camera.position.x = Math.max(viewport.getWorldWidth() / 2 + cameraMinX, camera.position.x); 185 | 186 | float top = zoom != 1 ? 5 : cameraTop; 187 | float bottom = zoom != 1 ? 0 : cameraBottom; 188 | float maxY = player.position.y + viewport.getWorldHeight() / 2 - bottom; 189 | float minY = player.position.y - viewport.getWorldHeight() / 2 + top; 190 | if (camera.position.y < minY) { 191 | camera.position.y += (minY - camera.position.y) * cameraSpeed / zoom * delta; 192 | if (Math.abs(camera.position.y - minY) < 0.1f) camera.position.y = minY; 193 | } else if (camera.position.y > maxY) { 194 | camera.position.y += (maxY - camera.position.y) * cameraSpeed / zoom * delta; 195 | if (Math.abs(camera.position.y - maxY) < 0.1f) camera.position.y = maxY; 196 | } 197 | 198 | camera.update(); 199 | batch.setProjectionMatrix(camera.combined); 200 | mapRenderer.setView(camera); 201 | 202 | camera.position.add(-shakeX, -shakeY, 0); 203 | shakeX = 0; 204 | shakeY = 0; 205 | } 206 | 207 | void render () { 208 | viewport.apply(); 209 | 210 | Gdx.gl.glClearColor(0, 0, 0, 1); 211 | Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 212 | 213 | if (ui.bgButton.isChecked()) { 214 | mapRenderer.setBlending(false); 215 | mapRenderer.render(mapLayersOpaque1); 216 | 217 | mapRenderer.setBlending(true); 218 | mapRenderer.render(mapLayersBackground2); 219 | } 220 | 221 | batch.begin(); 222 | // Draw enemies. 223 | for (Enemy enemy : model.enemies) { 224 | enemy.view.skeleton.getColor().a = Math.min(1, enemy.deathTimer / Enemy.fadeTime); 225 | skeletonRenderer.draw(batch, enemy.view.skeleton); 226 | } 227 | // Draw player. 228 | if (player.collisionTimer < 0 || (int)(player.collisionTimer / flashTime * 1.5f) % 2 != 0) 229 | skeletonRenderer.draw(batch, player.view.skeleton); 230 | batch.end(); 231 | 232 | if (ui.bgButton.isChecked()) { 233 | mapRenderer.setBlending(false); 234 | mapRenderer.render(mapLayersOpaque3); 235 | 236 | mapRenderer.setBlending(true); 237 | mapRenderer.render(mapForegroundLayers4); 238 | } 239 | 240 | batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE); 241 | batch.begin(); 242 | 243 | // Draw bullets. 244 | TextureRegion bulletRegion = assets.bulletRegion; 245 | float bulletWidth = bulletRegion.getRegionWidth() * scale; 246 | float bulletHeight = bulletRegion.getRegionHeight() * scale / 2; 247 | for (int i = 2, n = model.bullets.size; i < n; i += 5) { 248 | float x = model.bullets.get(i), y = model.bullets.get(i + 1); 249 | float angle = model.bullets.get(i + 2); 250 | float vx = MathUtils.cosDeg(angle); 251 | float vy = MathUtils.sinDeg(angle); 252 | // Adjust position so bullet region is drawn with the bullet position in the center of the fireball. 253 | x -= vx * bulletWidth * 0.65f; 254 | y -= vy * bulletWidth * 0.65f; 255 | x += vy * bulletHeight / 2; 256 | y += -vx * bulletHeight / 2; 257 | batch.draw(bulletRegion, x, y, 0, 0, bulletWidth, bulletHeight, 1, 1, angle); 258 | } 259 | 260 | // Draw hit markers. 261 | TextureRegion hitRegion = assets.hitRegion; 262 | Color color = batch.getColor().set(1, 1, 1, 1); 263 | float hitWidth = hitRegion.getRegionWidth() * scale; 264 | float hitHeight = hitRegion.getRegionWidth() * scale; 265 | for (int i = hits.size - 4; i >= 0; i -= 4) { 266 | float time = hits.get(i); 267 | float x = hits.get(i + 1); 268 | float y = hits.get(i + 2); 269 | float angle = hits.get(i + 3); 270 | color.a = time / bulletHitTime; 271 | batch.setColor(color); 272 | float vx = MathUtils.cosDeg(angle); 273 | float vy = MathUtils.sinDeg(angle); 274 | // Adjust position so bullet region is drawn with the bullet position in the center of the fireball. 275 | x += vy * bulletHeight * 0.2f; 276 | y += -vx * bulletHeight * 0.2f; 277 | batch.draw(hitRegion, x - hitWidth / 2, y, hitWidth / 2, 0, hitWidth, hitHeight, 1, 1, angle); 278 | } 279 | batch.setColor(Color.WHITE); 280 | 281 | batch.end(); 282 | batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); 283 | 284 | if (ui.bgButton.isChecked()) mapRenderer.render(mapForegroundLayers5); 285 | 286 | ui.render(); 287 | } 288 | 289 | void resize (int width, int height) { 290 | viewport.update(width, height); 291 | camera.position.x = player.position.x; 292 | camera.position.y = player.position.y + viewport.getWorldHeight() / 2 - cameraBottom; 293 | mapRenderer.setView(camera); 294 | ui.resize(width, height); 295 | } 296 | 297 | public boolean touchDown (int screenX, int screenY, int pointer, int button) { 298 | touched = true; 299 | player.view.shoot(); 300 | return true; 301 | } 302 | 303 | public boolean touchUp (int screenX, int screenY, int pointer, int button) { 304 | touched = false; 305 | return true; 306 | } 307 | 308 | public boolean keyDown (int keycode) { 309 | switch (keycode) { 310 | case Keys.W: 311 | case Keys.UP: 312 | case Keys.SPACE: 313 | if (player.hp == 0) return false; 314 | jumpPressed = true; 315 | if (player.isGrounded()) player.view.jump(); 316 | return true; 317 | case Keys.A: 318 | case Keys.LEFT: 319 | leftPressed = true; 320 | return true; 321 | case Keys.D: 322 | case Keys.RIGHT: 323 | rightPressed = true; 324 | return true; 325 | } 326 | return false; 327 | } 328 | 329 | public boolean keyUp (int keycode) { 330 | switch (keycode) { 331 | case Keys.W: 332 | case Keys.UP: 333 | case Keys.SPACE: 334 | if (player.hp == 0) return false; 335 | // Releasing jump on the way up reduces jump height. 336 | if (player.velocity.y > 0) player.velocity.y *= jumpDamping; 337 | jumpPressed = false; 338 | return true; 339 | case Keys.A: 340 | case Keys.LEFT: 341 | leftPressed = false; 342 | return true; 343 | case Keys.D: 344 | case Keys.RIGHT: 345 | rightPressed = false; 346 | return true; 347 | } 348 | return false; 349 | } 350 | 351 | /** Stores information needed by the view for a character state. */ 352 | static class StateView { 353 | Animation animation; 354 | boolean loop; 355 | // Controls the start frame when changing from another animation to this animation. 356 | ObjectFloatMap startTimes = new ObjectFloatMap(); 357 | float defaultStartTime; 358 | } 359 | } 360 | -------------------------------------------------------------------------------- /update-dependencies.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | mvn eclipse:eclipse 3 | -------------------------------------------------------------------------------- /update-dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mvn eclipse:eclipse 3 | --------------------------------------------------------------------------------