Giter Club home page Giter Club logo

headoverheels's Introduction

Head over Heels

The free and open source remake of the Jon Ritman and Bernie Drummond’s game

The Story

This repository originated with version 1.0.1 by Jorge Rodríguez Santos aka helmantika which I found on http://www.headoverheels2.com/

Jorge Rodríguez Santos wrote :

In summer 2001 I decided to achieve the goal of programming a remake of Head over Heels. The first stage arrived two years later, when I published a beta version of it. That experience was a really extraordinary one; above all, because of all the support I received from so many people that, in one way or another, collaborated to make possible that the project saw finally the light. Although the game credits are a good proof of it, I would specifically mention in these pages the participation, as the graphic designer, of Davit Masiá. Without his work, I could never complete my own one.

Unfortunately, I couldn’t develop that beta into an stable version because, for almost three years, I went through personal circumstances I prefer to forget. However, once I was able to recover my free time and feeling, as I felt, that I had a thorn in my side for not having finished the «remake», I decided to return to the project. Ignacio Pérez Gil had released the 0.3 version of his isometric engine Isomot, and I took it as the basis from which I reconsidered the work. In 2007, with most of the code already finished, I decided to reopen the forum.

These last two years have been ones of hard work, but a very gratifying one for the same reason the first part was: the unconditional support from several persons that have always paid attention to the evolution of the game. I’d like to thank, from my heart, to Santiago Acha, Xavi Colomé, Paco Santoyo and Hendrik Bezuidenhout their support and the good moments they have given me.

I found it in the fall of 2016 and saw that the sources lack a (sup)port for Mac OS X at all, and in particular for OS X on PowerPC, therefore I began this project on GitHub which eventually evolved into what it is now.

However, till the end of 2023 this project went almost unnoticed. Neither Jorge nor anyone else from the original team was ever participated in any further development and never wrote a single line about what’s goin’ on or was done here. https://osgameclones.com/ was perhaps the only lone site on which a link to this repo ever appeared. In the spring of 2019, I’ve lost all my interest and almost forgot about this project for 4.5 years...

...Until the fall of 2023, when François @kiwifb Bissy’s contribution awakened my care. And then, finalmente, Jorge came to this project. At the end of 2023 we were sharing various stories via email. His new site features the article about this project

The Present & The Future

I reworked almost every piece of the Jorge’s code, dealed around many gotchas and added many new features like

  • animated movin’n‘binkin dudes in the menus
  • transitions between the user interface menus
  • the new black & white set of graphics
  • ... with the speccy-like coloring of rooms
  • the room entry tunes
  • room miniatures
  • the camera optionally follows the active character
  • accelerated falling
  • support for various screen sizes not only 640 x 480
  • support for both the allegro 5 and allegro 4 libraries
  • the many easy-to-enable cheats :O

But yep, all of this is still quite “raw” for now and really needs some more love. Any playing, testing, issues found, spreading a word about this project somewhere, and other contributions are welcome. Especially patches, these are very much welcome ;)

Building

Since I’m currently using the GNU/Linux operating system, I’ll describe how to build and run this game on GNU/Linux with the “apt” package manager (Debian, Ubuntu and others)

For sure, you already know what the console aka terminal is, already did sudo apt-get install git for any deals with GitHub, and cloned the game’s repository somewhere on your local storage. Having a completely fresh system in which nothing was compiled before, to get all the things needed for building at once, just type

sudo apt-get install build-essential binutils make cmake autoconf automake libtool

And yep, don’t forget libx11-dev for the “allegro” library (#37 (comment))

sudo apt install libx11-dev

Then building the “Head over Heels” game on GNU/Linux is pretty easy with the build scripts I provided. All the used dependencies will be built too. The first script is

./linux-build.sh

It produces a binary that works through the allegro version 4 library (which is quite outdated). To get a binary running over the newer allegro version 5 (however, it is currently slower than over allegro4), use

./extras/linux-allegro5-build.sh

(install libgl1-mesa-dev package if you see the “X11 support currently requires OpenGL or OpenGL ES support” error and libxcursor-dev on “Looking for XcursorImageCreate in Xcursor - not found : X11 support requires Xcursor library”)

sudo apt install libgl1-mesa-dev libxcursor-dev

Okay, now you have a new and successful build of the game. Unedited linux-build.sh script installs the game inside your build directory at where-the-build-dir-is/_rootdir, thus type

cd _rootdir
bin/headoverheels

just after finishing a build to get the game running! 😲🥹😌

If something ’s wrong there

Don’t hear any music and sounds (with allegro 4)? Previously, I used padsp to deal with this... But then I installed some packages, namely libpulse-dev, libsndfile1-dev and libasound2-dev, and the subsequent full build played sounds and music just out of the box. So the solution is

sudo apt install -y libpulse-dev libsndfile1-dev libasound2-dev

before ./linux-build.sh

Any other gotchas? Feel free to write and ask 😚

headoverheels's People

Contributors

attuska avatar dougmencken avatar kiwifb avatar vadiqueme avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

headoverheels's Issues

Need to add auto~position of widgets, and thus remove all these x= y= from xml files

Examples~
<text id="yep" x="0" y="0">
<text id="movenorth" x="68" y="132">

They are used yet to manually position some lines of text, like the very first line of menus. And sure, it’s tooBorin’Thing® to live with it

There’s at least gui/Font::getCharWidth(), and symbols of game fonts are monospaced. So implementing auto-alignment is not “so-unreal” thing, I bet

these three gotchas with swopping characters

Let the joined Head over Heels character stay below an elevator, wait when elevator lowers on top of character, then swap, swap, ... Magically, Head is on top of an elevator

head goes on elevation via swapping

Get funny BANG somehow related to FallKindOfActivity::assignAnchor~ when one of two characters in the same room is active and is under some door, then just swap ’em

When inactive character of two in the same room meets mortal item it turns into bubbles... Until swapping. And when active one dies too, that other would be lost forever. Maybe activate him in cases of meeting something mortal?

inactive dies

Heels cannot take the handbag

I don;t understand it. Head takes the horn without any trouble. But Heels cannot take the handbag, it just stays there like a normal object. Getting into contact with it go through https://github.com/dougmencken/HeadOverHeels/blob/master/src/behaviors/Special.cpp#L71 but no vanishing happens. It never goes into the Activity::Vanish switch.
Taking the horn with Heads also go through that line without any issues.

It seems the value of activity is not persistent between calls to Special::update() for the handbag.

compilation error

Compiling 6d3d54a fails:

Isomot.cpp: In member function ‘BITMAP* isomot::Isomot::update()’:
Isomot.cpp:417:51: error: invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]
char* fromLastSlash = std::strrchr( roomFile.c_str (), '/' );
~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
make[1]: *** [Makefile:1354: headoverheels-Isomot.o] Error 1

Building & running master on GNU/Linux

When I try to compile the code in my Debian Linux with the "cygwin-build.sh" script, I receive these errors:

Mediator.cpp: In member function ‘void isomot::Mediator::update()’:
Mediator.cpp:134:59: error: ‘class isomot::FreeItem’ has no member named ‘setWhichMask’
                         dynamic_cast< FreeItem * >( *f )->setWhichMask( WantMask );
                                                           ^~~~~~~~~~~~
Mediator.cpp:134:73: error: ‘WantMask’ was not declared in this scope
                         dynamic_cast< FreeItem * >( *f )->setWhichMask( WantMask );
                                                                         ^~~~~~~~
Mediator.cpp: In member function ‘void isomot::Mediator::remaskFreeItem(isomot::FreeItem*)’:
Mediator.cpp:226:47: error: ‘class isomot::FreeItem’ has no member named ‘setWhichMask’
                                 thatFreeItem->setWhichMask( WantMask );
                                               ^~~~~~~~~~~~
Mediator.cpp:226:61: error: ‘WantMask’ was not declared in this scope
                                 thatFreeItem->setWhichMask( WantMask );
                                                             ^~~~~~~~
Mediator.cpp: In member function ‘void isomot::Mediator::remaskGridItem(isomot::GridItem*)’:
Mediator.cpp:254:51: error: ‘class isomot::FreeItem’ has no member named ‘setWhichMask’
                                         freeItem->setWhichMask( WantMask );
                                                   ^~~~~~~~~~~~
Mediator.cpp:254:65: error: ‘WantMask’ was not declared in this scope
                                         freeItem->setWhichMask( WantMask );
                                                                 ^~~~~~~~
Mediator.cpp: In member function ‘void isomot::Mediator::reshadeGridItem(isomot::GridItem*)’:
Mediator.cpp:276:35: error: ‘class isomot::GridItem’ has no member named ‘setWhichShade’
                         gridItem->setWhichShade( WantShadow );
                                   ^~~~~~~~~~~~~
Mediator.cpp:276:50: error: ‘WantShadow’ was not declared in this scope
                         gridItem->setWhichShade( WantShadow );
                                                  ^~~~~~~~~~
Mediator.cpp:284:40: error: ‘class isomot::FloorTile’ has no member named ‘setWhichShade’
                 room->floor[ column ]->setWhichShade( WantShadow );
                                        ^~~~~~~~~~~~~
Mediator.cpp:284:55: error: ‘WantShadow’ was not declared in this scope
                 room->floor[ column ]->setWhichShade( WantShadow );
                                                       ^~~~~~~~~~
Mediator.cpp: In member function ‘void isomot::Mediator::reshadeFreeItem(isomot::FreeItem*)’:
Mediator.cpp:311:51: error: ‘class isomot::GridItem’ has no member named ‘setWhichShade’
                                         gridItem->setWhichShade( WantShadow );
                                                   ^~~~~~~~~~~~~
Mediator.cpp:311:66: error: ‘WantShadow’ was not declared in this scope
                                         gridItem->setWhichShade( WantShadow );
                                                                  ^~~~~~~~~~
Mediator.cpp:317:56: error: ‘class isomot::FloorTile’ has no member named ‘setWhichShade’
                                 room->floor[ column ]->setWhichShade( WantShadow );
                                                        ^~~~~~~~~~~~~
Mediator.cpp:317:71: error: ‘WantShadow’ was not declared in this scope
                                 room->floor[ column ]->setWhichShade( WantShadow );
                                                                       ^~~~~~~~~~
Mediator.cpp: In member function ‘void isomot::Mediator::shadeFreeItemsBeneathItem(isomot::Item*)’:
Mediator.cpp:336:43: error: ‘class isomot::FreeItem’ has no member named ‘setWhichShade’
                                 freeItem->setWhichShade( WantShadow );
                                           ^~~~~~~~~~~~~
Mediator.cpp:336:58: error: ‘WantShadow’ was not declared in this scope
                                 freeItem->setWhichShade( WantShadow );
                                                          ^~~~~~~~~~
Mediator.cpp: In member function ‘void isomot::Mediator::mask(isomot::FreeItem*)’:
Mediator.cpp:581:45: error: ‘class isomot::FreeItem’ has no member named ‘whichMask’
                                 ( freeItem->whichMask() != NoMask && itemToMaskWith->getTransparency() == 0 ) ||
                                             ^~~~~~~~~
Mediator.cpp:581:60: error: ‘NoMask’ was not declared in this scope
                                 ( freeItem->whichMask() != NoMask && itemToMaskWith->getTransparency() == 0 ) ||
                                                            ^~~~~~
Mediator.cpp:581:60: note: suggested alternative: ‘mask’
                                 ( freeItem->whichMask() != NoMask && itemToMaskWith->getTransparency() == 0 ) ||
                                                            ^~~~~~
                                                            mask
Mediator.cpp:582:51: error: ‘class isomot::FreeItem’ has no member named ‘whichMask’
                                 ( itemToMaskWith->whichMask() != NoMask && freeItem->getTransparency() == 0 ) )
                                                   ^~~~~~~~~
Mediator.cpp:612:24: error: ‘class isomot::FreeItem’ has no member named ‘whichMask’
         if ( freeItem->whichMask() != NoMask )
                        ^~~~~~~~~
Mediator.cpp:612:39: error: ‘NoMask’ was not declared in this scope
         if ( freeItem->whichMask() != NoMask )
                                       ^~~~~~
Mediator.cpp:612:39: note: suggested alternative: ‘mask’
         if ( freeItem->whichMask() != NoMask )
                                       ^~~~~~
                                       mask

"setWhichMask", "whichMask", "setWhichShade" and so on only appear in "Mediator.cpp" file, nowhere else...

Port to Allegro 5

Allegro 5 is complete rewrite with a new API and hardware accelerated graphics

oh why did I poke at cygwin again

$ headoverheels
Segmentation fault (core dumped)

$ gdb /usr/bin/headoverheels.exe
GNU gdb (GDB) (Cygwin 12.1-1) 12.1
Reading symbols from /usr/bin/headoverheels.exe...
(gdb) run
Starting program: /usr/bin/headoverheels.exe
[New Thread 13852.0x196c]
[New Thread 13852.0x2698]
[New Thread 13852.0x37cc]
[New Thread 13852.0x204]

Thread 1 "headoverheels" received signal SIGSEGV, Segmentation fault.
0x00000001004037bf in iso::homePath () at Ism.cpp:160
160             if ( HomePath.empty () )
(gdb) bt
#0  0x00000001004037bf in iso::homePath () at Ism.cpp:160
#1  0x000000010044be74 in iso::GameManager::GameManager (this=0x1005223a0 <iso::GameManager::instance>) at GameManager.cpp:34
#2  0x00000001004f99ba in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at GameManager.cpp:25
#3  _GLOBAL__sub_I__ZN3iso11GameManager8instanceE () at GameManager.cpp:1197
#4  0x00007ffbcb8f6562 in cygwin1!.main () from /usr/bin/cygwin1.dll
#5  0x00000001004f80fd in main (argc=1, argv=0xa00001d70) at main.cpp:68
(gdb)

create AnimatedPicture

It would be nice to have animated movin’ n ‘binkin dudes in menus of user interface…

Maybe using algif’s algif_load_animation?

Update translations

Some items in menus are in english even when I choose русский language

is there any reason to have +1 tile for the absence of floor in a room ?

moreover, the related image files are completely identical, isn’t one of both enough?

$ sha256sum gamedata/gfx/jail.png/jail-nofloor-south.png 
5dbcdda3e12a78d0ca94d32a2e612606558a50204c8e0dd14eab7286f67c0e5a  gamedata/gfx/jail.png/jail-nofloor-south.png
$ sha256sum gamedata/gfx/jail.png/jail-nofloor-north.png 
5dbcdda3e12a78d0ca94d32a2e612606558a50204c8e0dd14eab7286f67c0e5a  gamedata/gfx/jail.png/jail-nofloor-north.png
$ sha256sum gamedata/gfx/jail.png/jail-nofloor-east.png 
ded0f8b77d99f8cea39d961bbec13e2d8124d9616cad4009edb26416db9471cc  gamedata/gfx/jail.png/jail-nofloor-east.png
$ sha256sum gamedata/gfx/jail.png/jail-nofloor-west.png 
ded0f8b77d99f8cea39d961bbec13e2d8124d9616cad4009edb26416db9471cc  gamedata/gfx/jail.png/jail-nofloor-west.png

Get wiser camera

Move camera smoothly when swopping characters in the same big room

Now it is too “ can’t live with it ”, and leaves artifacts

Which artifacts? Such ones

after-swop

the game bonuses re-appear after loading

after loading a saved game, all the bonuses~ and that very fish too~ are here as were not taken, ever

a saved game file contains the info about taken bonuses, but~ by some currently unknown reason(s)~ this info is lost on or just after loading a game

Firing donuts doesn't

When I fire donuts, the ball just stays in place and do not interact with anything, it does not have any effect at all.

Linux compilation error

In file included from Ism.cpp:2:
Ism.hpp: In function ‘std::string isomot::numberToString(int)’:
Ism.hpp:109:97: error: taking address of rvalue [-fpermissive]

Problem with locating data when game lives in PATH and user runs it just by its name

Something in the "Isomot" section is not good in commit 17e8a63.
The characters in menu before this commit are defective.

I get this error in gdb: (1.30 pre-release)

attila@localhost:~$ gdb headoverheels

GNU gdb (GDB) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-uhu-linux".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from headoverheels...(no debugging symbols found)...done.
(gdb) run
Starting program: /usr/bin/headoverheels 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/libthread_db.so.1".
[New Thread 0xf6e42b40 (LWP 29107)]
terminate called after throwing an instance of 'std::length_error'
  what():  basic_string::_M_create

Thread 1 "headoverheels" received signal SIGABRT, Aborted.
0xf7fd9a62 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
(gdb) bt
#0  0xf7fd9a62 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1  0xf7158dc0 in raise () from /lib/libc.so.6
#2  0xf715a287 in abort () from /lib/libc.so.6
#3  0xf744551f in __gnu_cxx::__verbose_terminate_handler() ()
   from /usr/lib/../lib/libstdc++.so.6
#4  0xf74430d4 in __cxxabiv1::__terminate(void (*)()) ()
   from /usr/lib/../lib/libstdc++.so.6
#5  0xf744314d in std::terminate() () from /usr/lib/../lib/libstdc++.so.6
#6  0xf7443401 in __cxa_throw () from /usr/lib/../lib/libstdc++.so.6
#7  0xf746deb6 in std::__throw_length_error(char const*) ()
   from /usr/lib/../lib/libstdc++.so.6
#8  0xf74daf10 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_create(unsigned int&, unsigned int) ()
   from /usr/lib/../lib/libstdc++.so.6
#9  0x0809e414 in ?? ()
#10 0x0809e81e in ?? ()
#11 0x080d25e0 in ?? ()
#12 0x080d3219 in ?? ()
#13 0x0804ec76 in ?? ()
#14 0xf7145356 in __libc_start_main () from /lib/libc.so.6
#15 0x0808af59 in ?? ()
(gdb) quit

Heels screen cannot be seen in full

I am trying to test HOH again, but when I get to Heels 5 screen, I cannot see full room, so I do not know where heels is if it out of screen.

heels1

heels2

Heels3

heel4

Screenshot_1

Hah, right to inviolability

Nothing happens when some free item like hunter robot touches active player. Player loses its life only when it initiates collision by itself

Instructions for installation on MacOS

Is the application available for installation on MacOS? If so, are there any instructions for how to install it?

If the app is in a finished state, should a link be added to the Wikipedia.org page?

(I'm struggling to understand the GitHub structure, so forgive me for these naïve questions 😊)

support many sizes of screen not just 640 x 480

The deauflt 640x480 window is too small, the minimum should be 800x600, even better 1024x769. In 16/9 monitors in fullsrceen everything is flat, since the original game is adapted to 3/4 monitors (TV). It would be useful to make the output screen adjustable.

#25 (comment)

room scrolling

When Head dies, you can't see him anymore, and the room is not scrollable

screen

player "head" is now in room "blacktooth/blacktooth58.xml"
copy of player "head" with behavior "behavior of Head" is created to rebuild this room
[New Thread 0xa517db40 (LWP 16602)]
[New Thread 0x9395ab40 (LWP 16603)]
playing Ogg music/jail.ogg
[Thread 0x9395ab40 (LWP 16603) exited]
metamorphosis of data for item "head" to data of "bubbles" initiated by "collide with mortal item"
[Thread 0xa517db40 (LWP 16602) exited]
parse "/usr/share/headoverheels/map/blacktooth/blacktooth58.xml"
creation of behavior "behavior of disappearance on jump into" for grid item "brick2" at x=208 y=63 z=0 with orientation "nowhere"
creation of behavior "behavior of disappearance on jump into" for grid item "brick2" at x=0 y=191 z=0 with orientation "nowhere"
creation of behavior "behavior of conveyor" for grid item "conveyor-belt" at x=112 y=159 z=0 with orientation "north"
creation of behavior "behavior of conveyor" for grid item "conveyor-belt" at x=128 y=159 z=0 with orientation "east"
creation of behavior "behavior of conveyor" for grid item "conveyor-belt" at x=128 y=143 z=0 with orientation "east"
creation of behavior "behavior of detector" for free item "bomb" at x=146 y=93 z=24 with orientation "nowhere"
creation of behavior "behavior of detector" for free item "bomb" at x=98 y=189 z=24 with orientation "nowhere"
free item with coordinates 0, 9, 1 is absent
got player "head" who entered this room @ MapManager::rebuildRoom
player "head" is now in room "blacktooth/blacktooth58.xml"
copy of player "head" with behavior "behavior of Head" is created to rebuild this room
[New Thread 0xa517db40 (LWP 16604)]

head

Problems with shadows

Why that same shadow needs to be casted nine times?

casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=144
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=144 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "bars-ns" at x=4 y=127 z=96 on free item "bars-ns" at x=4 y=127 z=48
casting shadow from free item "extra-life" at x=2 y=125 z=168 on free item "bars-ns" at x=4 y=127 z=48

need compatibility for OS X

HeadOverHeels remake is not yet compatible with OS X

_update_° it compiles now but still has some problems

Gotchas of video menu

I begin with such thing as Need To Tap ESCAPE Twice when you enter submenu “Choose set of graphics”, and then wish to return to main menu

Then yep, settings of “video” menu are ephemeral, id est not serialized, not saved to file, and not read from that file

Another gotcha is that “free items” don’t update their graphics after loading it once. To see it— begin a game, exit it, change set of graphics, begin another game, enjoy the mix

if there’s no background picture, don’t crash please

I used the same machine and OS as time ago with GCC 13, now the program crashes when starts, i compiled the program using the script linux-build.sh as other times.

OS: Linux Mint 19.3 Mate x86_64

games/hoh2$ ./headoverheels
whereIsGame is "./headoverheels"
FullPathToGame is "/home/mint/games/hoh2/./headoverheels"
can’t read game’s preferences from "/home/mint/.headoverheels/preferences.xml"
ALSA lib pcm_dmix.c:1089:(snd_pcm_dmix_open) unable to open slave
SharePath is "/home/mint/games/hoh2/share/headoverheels/"
read list of sounds from sounds.xml
language "en_US"
parsing "/home/mint/games/hoh2/share/headoverheels/text/en_US.xml"
going to create new screen for action " CreateLanguageMenu "
file "/home/mint/games/hoh2/share/headoverheels/letters.utf8" has table for 336 letters
Shutting down Allegro due to signal #11
Segmentation fault (core dumped

Taking an item out of the handbag make the game crash with SIGABRT (Linux)

So, now that I have the handbag I want to use it to get to the next room. But taking the item out of the bag crash the game.
Full backtrace

(gdb) bt full
#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=140661107476032) at ./nptl/pthread_kill.c:44
        tid = <optimized out>
        ret = 0
        pd = 0x7fee37584640
        old_mask = {__val = {0 <repeats 16 times>}}
        ret = <optimized out>
        pd = <optimized out>
        old_mask = <optimized out>
        ret = <optimized out>
        tid = <optimized out>
        ret = <optimized out>
        resultvar = <optimized out>
        resultvar = <optimized out>
        __arg3 = <optimized out>
        __arg2 = <optimized out>
        __arg1 = <optimized out>
        _a3 = <optimized out>
        _a2 = <optimized out>
        _a1 = <optimized out>
        __futex = <optimized out>
        resultvar = <optimized out>
        __arg3 = <optimized out>
        __arg2 = <optimized out>
        __arg1 = <optimized out>
        _a3 = <optimized out>
        _a2 = <optimized out>
        _a1 = <optimized out>
        __futex = <optimized out>
        __private = <optimized out>
        __oldval = <optimized out>
        result = <optimized out>
#1  __pthread_kill_internal (signo=6, threadid=140661107476032) at ./nptl/pthread_kill.c:78
No locals.
#2  __GI___pthread_kill (threadid=140661107476032, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
No locals.
#3  0x00007fee504c3476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
        ret = <optimized out>
#4  0x00007fee504a97f3 in __GI_abort () at ./stdlib/abort.c:79
        save_stage = 1
        act = {__sigaction_handler = {sa_handler = 0x0, sa_sigaction = 0x0}, sa_mask = {__val = {0 <repeats 13 times>, 10, 
              140661528049312, 140661107476032}}, sa_flags = 1347454650, sa_restorer = 0x7fee04086458}
        sigs = {__val = {32, 0 <repeats 15 times>}}
#5  0x00007fee50852b9e in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
No symbol table info available.
#6  0x00007fee5085e20c in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
No symbol table info available.
#7  0x00007fee5085e277 in std::terminate() () from /lib/x86_64-linux-gnu/libstdc++.so.6
No symbol table info available.
#8  0x00007fee5085e4d8 in __cxa_throw () from /lib/x86_64-linux-gnu/libstdc++.so.6
No symbol table info available.
#9  0x00007fee50855344 in std::__throw_logic_error(char const*) () from /lib/x86_64-linux-gnu/libstdc++.so.6
No symbol table info available.
#10 0x00005556578b378c in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*> (__end=0x1 <error: Cannot access memory at address 0x1>, __beg=0x0, this=<optimized out>)
    at /usr/include/c++/11/bits/basic_string.tcc:206
        __dnew = <optimized out>
        __dnew = <optimized out>
#11 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<std::allocator<char> > (__a=..., 
    __s=0x0, this=<optimized out>) at /usr/include/c++/11/bits/basic_string.h:539
        __end = 0x1 <error: Cannot access memory at address 0x1>
#12 iso::UserControlled::dropItem (this=<optimized out>, player=...) at behaviors/UserControlled.cpp:517
        freeItem = {pointer = 0x7fee04039ea0}
#13 0x00005556578a4e5f in iso::PlayerHeels::update (this=0x555658166430) at behaviors/PlayerHeels.cpp:137
        playerItem = @0x55565ac7a380: {<iso::FreeItem> = {<iso::Item> = {<iso::Mediated> = {
                _vptr.Mediated = 0x55565790f960 <vtable for iso::PlayerItem+16>, mediator = 0x5556597fab80}, <iso::Shady> = {
                _vptr.Shady = 0x55565790fa00 <vtable for iso::PlayerItem+176>, wantShadow = true}, 
              static poolOfPictures = 0x5556580d0750, descriptionOfItem = 0x5556598e0db0, 
              uniqueName = "character heels @ blacktooth27fish.xml", originalLabel = "heels", processedImage = {
    pointer = 0x55565bb4faa0}, height = 24, orientation = "west", currentFrame = 4, backwardsMotion = false, offset = {first = -185, 
                second = 110}, collisionDetector = true, motion = std::vector of length 16, capacity 16 = {{
                  pointer = 0x7fee04036670}, {pointer = 0x7fee04037d60}, {pointer = 0x7fee04039450}, {pointer = 0x7fee04022740}, {
                  pointer = 0x7fee04022b50}, {pointer = 0x7fee04022f60}, {pointer = 0x7fee04032440}, {pointer = 0x7fee04032850}, {
                  pointer = 0x7fee04032c60}, {pointer = 0x7fee04033070}, {pointer = 0x7fee04033480}, {pointer = 0x7fee04037f80}, {
                  pointer = 0x7fee04038390}, {pointer = 0x7fee040387a0}, {pointer = 0x7fee04038bb0}, {pointer = 0x7fee04038fc0}}, 
              shadows = std::vector of length 16, capacity 16 = {{pointer = 0x7fee04023780}, {pointer = 0x7fee04049030}, {
                  pointer = 0x7fee0404a830}, {pointer = 0x7fee0404bf40}, {pointer = 0x7fee0404d630}, {pointer = 0x7fee0404da50}, {
                  pointer = 0x7fee0404de70}, {pointer = 0x7fee0404e290}, {pointer = 0x7fee04029800}, {pointer = 0x7fee0402aef0}, {
                  pointer = 0x7fee0402c5e0}, {pointer = 0x7fee0402dcd0}, {pointer = 0x7fee0402f3c0}, {pointer = 0x7fee04030ab0}, {
                  pointer = 0x7fee040321a0}, {pointer = 0x7fee04073b30}}, motionTimer = std::unique_ptr<Timer> = {
                get() = 0x55565a60dc30}, behavior = 0x555658166430, anchor = "drum 1st", xYet = 51, yYet = 143, 
              zYet = 48}, <Drawable> = {_vptr.Drawable = 0x55565790fa20 <vtable for iso::PlayerItem+208>}, 
            static farFarAway = -1024, originalCellX = -1024, originalCellY = -1024, originalCellZ = -1024, wantMask = {
              value = 11}, transparency = 0 '\000', frozen = false, partOfDoor = false, shadedNonmaskedImage = {
              pointer = 0x55565bfdafc0}}, lives = 8 '\b', highSpeed = 0, highJumps = 0, 
          tools = std::vector of length 1, capacity 1 = {"handbag"}, howManyDoughnuts = 0, wayOfExit = "no exit", 
          wayOfEntry = "via second teleport", shieldTimer = std::unique_ptr<Timer> = {get() = 0x55565bf0d420}, 
          shieldRemaining = 0, descriptionOfTakenItem = 0x55565916f860, 
          behaviorOfTakenItem = "behavior of thing able to move by pushing"}
#14 0x000055565782ea9b in iso::Mediator::update (this=0x5556597fab80) at Mediator.cpp:123
        f = {pointer = 0x55565ac7a380}
        vanishedGridItems = std::vector of length 0, capacity 0
        vanishedFreeItems = std::vector of length 0, capacity 0
        playersInRoom = std::vector of length -1073585200782584444, capacity 1 = {{
            pointer = 0x55565790e430 <vtable for allegro::Pict+16>}, {pointer = 0x7fee04045930}, {pointer = 0x7fee50004500}, {
            pointer = 0x35}, {pointer = 0x55565790e450 <vtable for allegro::Sample+16>}, {pointer = 0x0}, {
            pointer = 0xffffffff00000000}, {pointer = 0x0}, {pointer = 0x0}, {pointer = 0x35}, {
            pointer = 0x55565790e450 <vtable for allegro::Sample+16>}, {pointer = 0x0}, {pointer = 0xffffffff00000000}, {
            pointer = 0x0}, {pointer = 0x0}, {pointer = 0x35}, {pointer = 0x55565790e450 <vtable for allegro::Sample+16>}, {
            pointer = 0x0}, {pointer = 0xffffffff00000000}, {pointer = 0x0}, {pointer = 0x2000000000}, {pointer = 0x35}, {
            pointer = 0x55565790e450 <vtable for allegro::Sample+16>}, {pointer = 0x0}, {pointer = 0xffffffff00000000}, {
            pointer = 0x10000000000}, {pointer = 0x3f4ececf3f800000}, {pointer = 0x35}, {
            pointer = 0x55565790e450 <vtable for allegro::Sample+16>}, {pointer = 0x0}, {pointer = 0xffffffff00000000}, {
            pointer = 0x0}, {pointer = 0x0}, {pointer = 0x35}, {pointer = 0x55565790e450 <vtable for allegro::Sample+16>}, {
            pointer = 0x0}, {pointer = 0xffffffff00000000}, {pointer = 0x55565bff6a00}, {pointer = 0x0}, {pointer = 0x25}, {
            pointer = 0x7fee04045}, {pointer = 0x40e33cf4b4e6c948}, {pointer = 0x7fee50a8b2b0 <al_destroy_bitmap>}, {
            pointer = 0x55}, {pointer = 0x7fee00000001}, {pointer = 0x7fee04046070}, {pointer = 0x7fee04035590}, {pointer = 0x0}, {
            pointer = 0x7fee04045560}, {pointer = 0x7fee04045478}, {pointer = 0xf}, {pointer = 0x7267656c6c61374e}, {
            pointer = 0x4574636950346f}, {pointer = 0x55}, {pointer = 0x700000000}, {pointer = 0x55565a60e5d0}, {pointer = 0x0}, {
            pointer = 0x0}, {pointer = 0x55565a615ed0}, {pointer = 0x7fee04044ea0}, {pointer = 0x7fee04044ea0}, {
            pointer = 0x7fee04044ea8}, {pointer = 0x0}, {pointer = 0x55}, {pointer = 0x7fee00000000}, {pointer = 0x5556598c7ea0}, {
            pointer = 0x0}, {pointer = 0x0}, {pointer = 0x55565a615ed0}, {pointer = 0x7fee04045518}, {pointer = 0xf}, {
            pointer = 0x7267656c6c61374e}, {pointer = 0x4574636950346f}, {pointer = 0x35}, {pointer = 0x55565bf02478}, {
            pointer = 0x7fee040000b0}, {pointer = 0x0}, {pointer = 0x55565991e430}, {pointer = 0x30}, {pointer = 0x25}, {
            pointer = 0x55565b877f38}, {pointer = 0x0}, {pointer = 0x7fee5000456d}, {pointer = 0x35}, {
            pointer = 0x55565790e450 <vtable for allegro::Sample+16>}, {pointer = 0x0}, {pointer = 0xffffffff00000000}, {
            pointer = 0x0}, {pointer = 0x4000000000}, {pointer = 0x35}, {
            pointer = 0x55565790e450 <vtable for allegro::Sample+16>}, {pointer = 0x0}, {pointer = 0xffffffff00000000}, {
            pointer = 0x4000000000}, {pointer = 0x0}, {pointer = 0x35}, {
            pointer = 0x55565790e450 <vtable for allegro::Sample+16>}, {pointer = 0x0}, {pointer = 0xffffffff00000000}, {
            pointer = 0x4}, {pointer = 0x3f800000}, {pointer = 0x35}, {pointer = 0x55565790e450 <vtable for allegro::Sample+16>}, {
            pointer = 0x0}, {pointer = 0xffffffff00000000}, {pointer = 0x3f800000}, {pointer = 0x0}, {pointer = 0x35}, {
            pointer = 0x55565790e450 <vtable for allegro::Sample+16>}, {pointer = 0x0}, {pointer = 0xffffffff00000000}, {
            pointer = 0x0}, {pointer = 0x0}, {pointer = 0x35}, {pointer = 0x55565790e450 <vtable for allegro::Sample+16>}, {
            pointer = 0x0}, {pointer = 0xffffffff00000000}, {pointer = 0x0}, {pointer = 0x0}, {pointer = 0x35}, {
            pointer = 0x55565790e450 <vtable for allegro::Sample+16>}, {pointer = 0x0}, {pointer = 0xffffffff00000000}, {
            pointer = 0x3f800000}, {pointer = 0x3f800000}, {pointer = 0x35}, {
            pointer = 0x55565790e450 <vtable for allegro::Sample+16>}, {pointer = 0x0}, {pointer = 0xffffffff00000000}, {
            pointer = 0x0}, {pointer = 0x0}, {pointer = 0x35}, {pointer = 0x55565790e450 <vtable for allegro::Sample+16>}, {
            pointer = 0x0}, {pointer = 0xffffffff00000000}, {pointer = 0x55565bfd28c0}, {pointer = 0x0}, {pointer = 0x1b5}, {
            pointer = 0x0}, {pointer = 0x2190000000a}, {pointer = 0x0}, {pointer = 0x0}, {pointer = 0x4000000000}, {
            pointer = 0x10000000028}, {pointer = 0x4000000000}, {pointer = 0x2800000000}, {pointer = 0x0}, {
            pointer = 0x4000000000}, {pointer = 0x28}, {pointer = 0x7fee0409b730}, {pointer = 0x1}, {pointer = 0x7fee0409b730}, {
            pointer = 0x1000000000a}, {pointer = 0x4}, {pointer = 0x3f800000}, {pointer = 0x0}, {pointer = 0x3f80000000000000}, {
            pointer = 0x0}, {pointer = 0x0}, {pointer = 0x3f800000}, {pointer = 0x0}, {pointer = 0x3f80000000000000}, {
            pointer = 0x3f800000}, {pointer = 0x0}, {pointer = 0x3f80000000000000}, {pointer = 0x0}, {pointer = 0x0}, {
            pointer = 0x3f800000}, {pointer = 0x0}, {pointer = 0x3f80000000000000}, {pointer = 0x3d00000000000000}, {
            pointer = 0x0}, {pointer = 0x0}, {pointer = 0xbd4ccccd}, {pointer = 0x0}, {pointer = 0x3f80000000000000}, {
            pointer = 0xbf80000000000000}, {pointer = 0x3f800000}, {pointer = 0x3f800000}, {pointer = 0x0}, {pointer = 0x0}, {
            pointer = 0x0}, {pointer = 0x0}, {pointer = 0x0}, {pointer = 0x0}, {pointer = 0x0}, {pointer = 0x0}, {
            pointer = 0x7fee0409b730}, {pointer = 0x0}, {pointer = 0x55565bfc7710}, {pointer = 0x0}, {pointer = 0x55}, {
            pointer = 0x700000001}, {pointer = 0x55565a793400}, {pointer = 0x55565a796140}, {pointer = 0x55565a795fe0}, {
            pointer = 0x55565a795f70}, {pointer = 0x7fee04046ad0}, {pointer = 0x7fee04046ad0}, {pointer = 0x7fee04046ad8}...}
#15 0x000055565782f128 in iso::Mediator::updateThread (mediatorAsVoid=0x5556597fab80) at Mediator.cpp:196
        mediator = 0x5556597fab80
#16 0x00007fee50515b43 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
        ret = <optimized out>
        pd = <optimized out>
        out = <optimized out>
        unwind_buf = {cancel_jmp_buf = {{jmp_buf = {140725039088960, -1007450437748141918, 140661107476032, 11, 140661526452304, 
                140725039089312, 997757987058995362, 997672148870353058}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 
              0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
        not_first_call = <optimized out>
#17 0x00007fee505a7a00 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
No locals.

Raspberry Pi: Keyboard recognized in Menu but not in Game

Describe the bug
On a Raspberry Pi the binary can be started and shows up the menu. In the menu navigation works with keyboard controls but after starting a new game the keyboard events are no longer recognized.

Allegro Lib
Tested with 4.4.3.1 (bundled with this repo) as well as with 4.4.2.1 from Raspi OS Buster.

To Reproduce
Steps to reproduce the behavior:

  1. Build this repo on Raspberry Pi
  2. Start headoverheels, navigate to new game
  3. Let game start
  4. Notice that no keyboard presses are recognized

Expected behavior
Keyboard should be usable in game.

Testsystem

  • OS: Raspi OS Buster (Debian 10)
  • Generic wired USB keyboard attached
  • Reproducable on Raspberry Pi 3 or Raspberry Pi 4

Additional context

PS: Thanks for reviving this classic game and gem.

chat about old and new segmentation faults, and other stuff (:

tor1
tor2

The game now always ends in segmentation faults

Play 1.

> playing Ogg music/blacktooth.ogg
[Thread 0xcdb38b40 (LWP 20104) exited]
creation of behavior "behavior of disappearance in time" for free item "bubbles" at x=80 y=15 z=48 with orientation "nowhere"
creation of behavior "behavior of disappearance in time" for free item "bubbles" at x=80 y=63 z=48 with orientation "nowhere"
creation of behavior "behavior of disappearance in time" for free item "bubbles" at x=130 y=61 z=72 with orientation "nowhere"
terminate called after throwing an instance of 'std::length_error'
  what():  basic_string::_M_create
>
>Thread 28 "headoverheels" received signal SIGABRT, Aborted.
[Switching to Thread 0xd282fb40 (LWP 20103)]
0xf7fd9a62 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
(gdb) bt
#0  0xf7fd9a62 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1  0xf7156dc0 in raise () from /lib/libc.so.6
#2  0xf7158287 in abort () from /lib/libc.so.6
#3  0xf744351f in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/../lib/libstdc++.so.6
#4  0xf74410d4 in __cxxabiv1::__terminate(void (*)()) () from /usr/lib/../lib/libstdc++.so.6
#5  0xf744114d in std::terminate() () from /usr/lib/../lib/libstdc++.so.6
#6  0xf7441401 in __cxa_throw () from /usr/lib/../lib/libstdc++.so.6
#7  0xf746beb6 in std::__throw_length_error(char const*) () from /usr/lib/../lib/libstdc++.so.6
#8  0xf74d8f10 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_create(unsigned int&, unsigned int) ()
   from /usr/lib/../lib/libstdc++.so.6

Play 2.

>   copy of character "heels" with behavior "behavior of Heels" is created to rebuild this room
[New Thread 0xd282fb40 (LWP 20244)]
>
>Thread 1 "headoverheels" received signal SIGSEGV, Segmentation fault.
0xf7f61340 in _linear_draw_sprite32 () from /usr/lib/../lib/liballeg.so.4.4
(gdb) bt
#0  0xf7f61340 in _linear_draw_sprite32 () from /usr/lib/../lib/liballeg.so.4.4
#1  0x0805584c in ?? ()

Play 3.

>character "head" is yet in room "blacktooth/blacktooth09.xml"
copy of character "head" with behavior "behavior of Head" is created to rebuild this room
[New Thread 0xd282fb40 (LWP 20315)]
creation of behavior "behavior of disappearance in time" for free item "bubbles" at x=80 y=15 z=48 with orientation "nowhere"
creation of behavior "behavior of disappearance in time" for free item "bubbles" at x=80 y=63 z=48 with orientation "nowhere"
creation of behavior "behavior of disappearance in time" for free item "bubbles" at x=130 y=61 z=72 with orientation "nowhere"
creation of behavior "behavior of disappearance in time" for free item "bubbles" at x=80 y=63 z=24 with orientation "nowhere"
>
>Thread 34 "headoverheels" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xd282fb40 (LWP 20315)]
0xf7253fb0 in __memcpy_ssse3 () from /lib/libc.so.6
(gdb) bt
#0  0xf7253fb0 in __memcpy_ssse3 () from /lib/libc.so.6

Heels can't pass from the second room

Hi! i complied without any issue the game and works great until i play with heels, he can't jump to the other rooms and gets stuck in the second room.

I made a gif with the possible issue
hoh

Final scene

Need some nice music for final scene. Maybe some looooong ‘n’ jazzy mix of various room entry tunes?

And yep, final room freezes after some time

Port to smartphones

At first, it needs support of mouse (clicking/tapping anywhere on the screen of game). And / or on~screen virtual joystick

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.