The HTML5 version of NeedForOrder is now free to play on itch.io, or you can download the Android version on the Google Play Store.
Second attempt at game development using the Godot engine with C#. Another abstract/clean/simple 2D-game without great expectations. Another much needed learnirng project, building on the (little) knowledge acquired in the making of StickyBlocks (give it a try: StickyBlocks in itch.io).
Reorganize some chaotically placed geometric objects at will following your inner NeedForOrder. You can choose to reorganize randomally placed lines, squares, dots and disks. There is no specific goal: create your pattern/order, lower the entropy. You can also choose to use a background (faded) pattern to inspire and facilitate your need for order.
- Build and complete another little abstract game (completely on my own)
- Learning new Godot specific stuff, for example: better use of collision layer, multi-resolution support, touchscreen inputs support, Android export, place annoying ads in game...
- Learning new C# stuff, I will try to use more C# specific features even if not necessary or more complex: interfaces, delegates, events(when to use events instead of Godot's signals?), "when to use inheritance?", namespaces, setters...
- Try to write more SOLID code, more reusable, more generic (...not high hopes about these...)
- Try a different (from StickyBlocks) game structure planned in UML: using more state machine pattern, some globals (when makes sense), some specific managers classes (inputs manager, UI manager, main manager,...)
- Put more faith in Godot and less in my maths skills (I studied theoretical physics): before going into the rabbit hole of mathematics, try to solve problems using Godot's features!
- Create a base game mechanics (select/drag/drop/rotate/scale) to be reused in the future in different games (for example in a abstract or also not abstract puzzle game).
- Created and setup the Godot project: 2d/expand/portrait mode
- Created and connected the repository to VSCoce
- Planned the base structure of different classes/nodes in UML
- Created folders and files structure for the base objects
- Created the
Mainnode structure it will contain: list of objects, UI stuff, some manager nodes - Created some base interfaces for different kind of geometrical object:
ISelectable,IMovable,IRotatable,IScalable. - Created
BaseObjectnode: aKinematicBody2Dwith a to-be-definedCollisionShape2D - Started to implemented
BaseObjectclass - Started to implemented
Main: game machine logic and selection input handler - Created a
Globalsnamespace:GAMESTATEandOBJECTSTATEenums,SCREENINFOstruct,RandomManagerstruct
- Created
LevelBarriersnode and class: limits the game area, responsive toViewport.size_changedsignal - All inputs are handled in
Mainin a main_UnhandleInputfunction that first handles in a generic way the selection/unselection of object and then callsInputControlFlowfunction of the selected object - Added a
Area2DcalledMouseArea: a smallCollisionShape2Dunder the mouse cursor, follows the mouse position - Create
RotatableObjectnode: inherited scene ofBaseObjectwith a secondKinematicBody2Dto be pressed to control the rotation → callsGetOverlappingBodies()in the selection/unselection input-handler function and returns the object on top - Created
RotatableObjectas child ofBaseObjectand asIRotatable: implemented theInputControlFlowfunction to handle motion/rotation → basically I recreated the selection/unselection/move/rotate functionalities of Godot's editor (or any 2d design software) but with the challenging interactions beetwen objects's motion/rotation andLevelBarriersconstraints - Implemented a
_overlapplevariable for the objects (modifies with code the collision layer/mask) - Created nodes and implemented classes of:
SquareObject,DotObject,DiskObject
- Refactored scenes folders, files name...
- Created and implemented
GameUI,ScrollGameUIscene as main UI elements, addedGameUIas child node ofMainscene in aCavasLayer - Created and implemented
ScrollObjectType(as child ofScrollGameUI) andScrollIconGameUI: change type of object, press and drag left/right the icons of the scrollbar (I did not useScrollContaineror similar), use tween to change Modulate and scale of selected/unselected icons, emitChangedObjectTypesignal toMain -
GameUIinput are handled by_input_eventsignal of theArea2Dspecific to aScrollGameUI - Added
PlayableSizeinGlobals.ScreenInfostruct:GameUIlimits the playable size (fromGetViewport().VisibleSizetoPlayableSize) - Created
LineObjectscene: child ofRotatableObjectwith aLine2D,LineObjectis defined by the angular coefficient_m($m$ ), x-axis intersection_x0($x_0$ ) and y-axis intersection_b($b$ ) - Implemented
LineObjectrandom initialization and selection area collsion: choose random_m,_x0and_b, calculate the two intesection points of this line withGlobals.PlayableSizeand set this points asLine2D.Points, store the center point of the line and update theSelectionAreaShapeshape -
LineObjecthas a specificCollisionLayer→ it did NOT interact directly withCollisionLayerofLevelBarriers; the center point of the line is contrainted to be in thePlayableSize -
LineObjectmotion: mouse movement is related to movement in the$(x_0, b)$ parameter-space, the mainKinematicBody2Ddoes not move, movement is in the$(x_0, b)$ parameter-space and update line points (intersection points with playable area) every frame (a mouse movement along the x-axis changes_x0, along the y-axis changes_b)
- Implemented
LineObjectrotation: similar to motion, rotation takes place on the_mparameter; before the rotation setup the rotation center: it is the current line center (respect the intersection points) → so set$(x_0,b)$ equals to the center point (does not change the line and put the center rotation in the correct position) - Implemented rotation snapping in
RotatableObject(to default snaps every 45° with a delta-angle threshold 3°): smooth rotation unless$|TargetAngle - MultipleOfSnappingAngle| < DeltaAngleThreshold$ - Refactored some code/inheritance structure in/of
RotationObject,LineObject,BaseObject: create some general function (likeInputRotationPressed,InputMovementMotion...) to be called in theHandleInputMotionandHandleInputRotationfunction → reduced copy and paste code and makes motion/rotation more general - Created
ScrollNumberandScrollNumberIconGameUIand connected toMain: scroll UI that can change number of objects spawned - Adeed
ScrollNumberto the main UI nodeGameUI
- Added
RandomizeButtontoGameUIand connected toMain: re-randomize objects property, not number of objects spawned - Implemented
RandomnizeObjectsinMainandRandomizeObjectinBaseObject, calls overridenInitRandomObjectand if necessary updates the others object members nedeed to redraw the object (like intersection points inLineObject) - Created
SaveHandlernamespace andSaveObjectsHandleras static class, contains:SaveObjectsandLoadObjects→ I followed Godot 3.4 docs, every time save function it's called it creates new dict (specific to current objects) for every objects and saves it in a JSON file; on load reads that specific file - On
ObjectTypeChangedandNumberChangedsignals emitted byScrollGameUI,Mainsaves current objects-configuration and loads objects from a file if it exits else callsSpawnRandomObjects; calling the save function a file with name${ObjectType}{NumberOfObjects}.saveis created BaseObject,RotatableObjectand every specific object hasCreateDictandLoadDatafunctions- Added a
Utilitiesstatic class inGlobalsnamespace, contains:ObjectTypeToStringandGetObjectScenePathfunctions - Created
ScrollBackgroundIconGameUIandScrollBackground: scroll icons to change background; contain a texture used as a tile (stretch mode Tile) to fill the background with a specific pattern
- Created save system for background, saves in
${ObjectType}{NumberOfObjects}Background.savethe last background-pattern used and when number/type is changed the corrisponding icon inScrollBackgroundit's seleceted; background saving separated to objects saving; - Added some "wait-till-tween-completed" logic for
GameUIscroll-icon input-events - Now
LineObjectupdates parameters on changes of the visibleRect area size - Now movable object updates to a valid position on changes of the visibleRect area size
- Setup some Android export stuff: Android export template, Android build template, AndroidStudio for testing and USB testing/debugging
- Setup some stuff to try to intoduce some studid and annoying ads on Android: NativeLib addons, Applovin account/test_device/Ad_unit/banner
- Create
AdsHandler(it's easier to use applovin_max autoloaded stuff in GDScript):loadBannerand signal_on_shown_bannerand_on_load_banner - Connected
AdsHandlerto main: show banner ads only when re-randomize objects (call GDscript from C# with Call function) - Now selection/unselection/movement support touch input (not in a optimal/generic way but it works): emulate mouse from touch input it's on and add some
IsPressedchecking - Create new collisions detection for selection/unselection method
ReturnTopObjectMobilefor touch input: desktop version uses theMouseArea.GetOverlappingBodiesfunction and upload mouse position every physic frame → not possible for touch input (updateMouseAreaposition only on touch); zero lenght raycast works strange with non-rectangular collision shape; Mobile version uses directlyPhysics2DDirectSpaceState.IntersectPoint(GetGlobalMousePosition(),...)→MouseAreanot needed - In
MainaddedReturnTopObjectdelegate and_returnTopObjectprivate member of typeReturnTopObject: on ready sets_returnTopObjecttoReturnTopObjectMobileorReturnTopObjectDesktopdepending onOS.HasTouchscreenUiHint()value - Change some scale factor/size of collsion shape of objects: they were too small for touch input (at least using my fingers...on my terrible phone...)
- Begun to think graphics/theme/colors stuff: blocknotes theme/doodle theme
- Add touch support for rotation input (NOT ELEGANT solution but it works, added a strange branch in
Maininput handler function only for rotatable object): mouse_entered and mouse_exited does not work with touch → only forIRotatableobjects inMainfirst check withPhysics2DDirectSpaceState.IntersectPoint(GetGlobalMousePosition(),...)if you are clicking on aRotationArea, if true then set_rotatablemember of selected object to true - Added some utility functions (
ObjectInterfacesstruct) and exported variable (forScrollGameUIelements)
- Add color on/off button:
ColorButtonobject - Connected color change to save system: save color option in background-save file
ScrollBackgroundnow automatically updates to correct icon when type or number of objects is changed- Created basic tile for the background patterns and added a offset variable to center the different patterns relative to each others
- Created
ColorObjectfunction inBaseObjectand refactored in a more object-oriented wayInitRandomObject/RandomizeObject; and a corrispondingColorObjectsinMain - Added in
Globalsa static class for the main object colors:Globals.Colors - Add some basic/terrible graphics (created using Krita): icon of tile for background patterns, background patterns tile, randomize button, color button, vertical line, setting icon, objects textures, settings panel and
GameUIpanel (post-it),RotationAreaicon - Copy and past this shader from a GDQuest's tutorial: color on/off of color button, if off set to a gray-scale-ish
- Some fixes and refactoring of: problem with line collision shape size and input event of
GameUI; problem with tween completed/started ofGameUIand gamestate flow (addedGAMESTATE.PAUSED); save system creates "a lot" of godot's dictionaries "problem" with GC;RotationAreais always the top shape when object selected;RotationAreaspawn position; ads frequency; double touch moving fromGameUItoPlayableSizearea; problem withLineObjectrotation SettingsPanel: allow to change default/base color and display version number; post-it theme; connected withMain- Small refactoring of
RotationAreacollision detection withLevelBarriers
- Setup draft project itch.io)
- Created app icon for mobile
- Created some gif/screenshots for itch.io page
- Fixed some inputs problems
- Reduced android export size: compiled godot mono version, created custom android export with all modules disabled (expect webp module), use_lto on, no debug symbols, commented out some ClassDB in register source file, use basic/default R8/ProGuard stuff in build.gradle file -> arm64_v8a + armebi_v7a (release_debug and release) from ~38MB to ~26,1MB export size (mono is 6.1 MB) (still something is unclear to me)
- Created Google Play Console account
- Created and setup app in Google Play Console (internal testing phase)
- Created some gif/screenshots for itch.io page
- Fixed some inputs problems
- Fixed some bugs: background save file, line movement, refactored out of bounds for itch.io HTML5-export problem ->
_Notification
- Created varius icon/cover image: itch.io cover image, google play cover image, google play main image, android app icon
- Fixed some small ads id unit problem
- Publish on itch.io (HTML5 version) and Google Play Store (Android version)






