Hacker News new | past | comments | ask | show | jobs | submit login
Open Golf: A cross-platform minigolf game written in C (github.com/mgerdes)
411 points by 10000truths on March 24, 2022 | hide | past | favorite | 92 comments



Just to be clear, folks, this isn’t my project. I saw this in /r/programming and it looked interesting, so I thought I’d share with you guys.


This is excellent. Can I suggest a couple of improvements?

1. Maybe have a "par" for each hole.

2. Be able to better see the layout of multi-level holes, i.e. the ones with slopes.

Other than that this is a really nice lunchtime distraction.


Loved it, and would concur that having a better sense of what the hole looks like from above before the shot (or being able to click to see the hole from above like a map) would be awesome. But, I loved playing it. And, I sucked.


I'm only now realizing how insanely erotic my last comment was....


Any recommendations to learn to build cross-platform games like this?

I work on frontend projects day-to-day. I'd love to build a simple cross-platform game in C/Zig/C++ for some variety and to learn lower-level programming.

I've looked at Handmade Hero in the past but its specific to Windows at the moment.


This might be obvious, but one of the key activities is to minimize platform-dependent code so that most of the game logic is portable and shared across all platforms. So no Win32-isms or Cocoa-isms or <unistd.h> littered all over your game.

One way (out of many) to do this is have a cross-platform interface for each non-portable thing, with separate platform-specific implementation files that you swap in depending on which platform build you're doing. For example, if your game has sound, you'll probably have a platform-independent sound.h the rest of the game calls into, and then sound_windows.c, sound_linux.c, sound_mac.c, etc. files that contain the platform-specific implementations of those functions. Repeat for graphics, input, and other things that cannot be done (or you don't want to do) in a portable way.

Another thing is the game loop. Back in the DOS days, when you were the only thing running on the system, you implement main() did something like:

    while (game_running) { do_everything(); }
Modern platforms expect to be in the driver seat, and will instead call into your code, so this turns into something like:

    function windows_call_me_please() {
        do_everything();
    }
Obviously this is a simplification, and there is a lot more to it, but hopefully it answers some basic questions.


Also choosing a base platform agnostic framework like SDL which has a lot of the OS interactions (keyboard & mouse) already abstracted away for you gets you pretty far on the cross-platform road.


Bonus points for the suggestion of using module_platform.c instead of #ifdef spaghetti.


Handmade Hero gives good advice how to modularize to make a game portable. For many things you want to achieve, you can have the platform call the game instead of the other way around. Essentially it's (asynchronous) event driven architecture which enforces modularization.

Think of a system as shipping data packets around, then it should be much easier to see how to swap out the platform parts.


It's all about the libraries. Use Sokol and Dear Imgui and you'll be cross platform.


Read everything on James Hague's "programming in the twenty first century", but start with "Living Inside Your Own Black Box":

https://prog21.dadgum.com/66.html

Libraries can be helpful. But at the baseline, what you have to solve is the problem of adjusting your dependency load such that adding new target platforms is a matter of rewriting small details, which means taking a language-designer's view of your system and saying "OK, if I need to automate the rewrite, then I need a compilation mechanism". Sometimes you have to change asset formats or runtime I/O mechanisms, but you can select what layer of the design you are aiming to standardize and go from there. e.g. records of chess games have a few defined formats. They don't need to track the assets used to draw the board, or the account information of the players.

If what you want is all of it: every pixel and frame of output the same, all input devices treated identically across all environments, then you'll gravitate towards a VM type of design, like Another World, Z-Machine or SCUMM, to name three well-known examples of such a design.


It’s 99% due to nostalgia but look at chocolate doom. It’s a tightly coded 2.5D game. There’s TONS of documentation on how it works. Recreating the engine in a familiar language and playing the WADs of you childhood is fun. But if you want 3d with OpenGL maybe look at quake. That’s how I learned GL.


Level 20, but wish there were more. The fun ones were trying to skip most of the course from the tee. Throw a leaderboard on there and no one's going to be working.

Great work, awesome orchestration of cross platform libs.


I think the game not having an online component is one of its charms. Simplicity in nature and execution is the obvious goal.

Have you seen the leaderboards of any online game lately? They usually get wrecked by cheaters and defeat the whole purpose.


Impressive to see C being able to create x-plat 3D games that run in Browser + popular Desktop + Mobile OS's.

Typically there's big companies with large dev teams working on accomplishing such a feat & this project does it with with a 50 year old language and a handful of libs


Not to diminish the value of their efforts, welcome to the days of 16 bit game programming, naturally minus the browser part.

Plenty of retrogaming stuff to learn from.


I've liked Raylib lately for writing graphicsy applications. Here's a small example that does 3d, runs in the browser, code shown below: https://www.raylib.com/examples/core/loader.html?name=core_3...


What's the TLDR on how to compile the C code to run in the browser?


Emscripten. If you use something like SDL porting is trivial.

Working on a project to port a 20 plus year old c/cpp code base to the web. The tooling was like 98% there but I've had to upstream a few fixes or find a workaround every now and then.


Good on you man. If I got an email that said “opportunity: port 20+ cpp app to web” I would chuckle and close that sucker real quick. Modern cpp I maybe can deal with. That 90s stuff is real bad.


It's actually a purely voluntary endeavor. I'm attempting to port a game engine called Zelda Classic to the web. So far, so good!


Here's a little template that uses Raylib: https://github.com/nikki93/raylib-template


Kind of looks like neverball/neverputt (https://neverball.org/).


Neverball also has a browser version that's compiled directly from the C code. (Shameless plug, I'm one of the developers.)

https://neverball.github.io/


It is remarkable to me that, once I’m in full screen mode and into a level, I can’t tell that this isn’t the desktop version. All the same crispness and responsiveness is there. I probably knew in my mind that this is possible these days, but every bit of muscle memory I apply here is telling me that Wasm, Emscripten, etc have become quite good, in a way that an unfamiliar game couldn’t tell me.

Thanks for giving me an easier way to share this good old game with friends!


Are you the same Penwielder who made Penwielders Scrapbook (a Neverball level)? I seem to have an uncanny memory of usernames from the old Neverball forum. Anyway, your name inspired me to find that level and add it to the in-game downloads.


How many changes to the C code are required for this sort of thing?


That depends on the code. Neverball has acquired a high level of portability thanks in large part to SDL2 and OpenGL (ES). So compiling to Emscripten was mostly about rearranging the pieces that were already there. My original patch was surprisingly small. (https://github.com/Neverball/neverball/commit/517c93b7bcf63f...) I would say I spent more time on integration with browser APIs, so it would behave and feel more like a web app.


Would be nice if some of this stuff were part of the toolchain/stdlib so it would be closer to a simple recompile.


This is great.


Here comes the nostalgia


Zany Golf


Request: since it's open source, put the android version on F-Droid as well. https://f-droid.org/


Error report: on hole 3, I was able to ramp off a bump and hit the hole with enough velocity that the ball clipped through into an underground area.


That was lots of fun!

I wish there is a replay mode so I can relish on my glorious strokes of luck.


I tried to analyze the running app with the Firefox dev console, but the GitHub hosted page said there were no sources!

Browsing the Sokol Github, it looks like it's compiling to web assembly. I'm not very familiar with web assembly, how does one normally debug it?


With the sokol libs as platform abstraction it works quite well to develop and debug a native build in a regular C/C++ IDE and then only cross-compile to WASM. Most bugs are platform agnostic and would also happen in the native build. For the rare case that problems only happen in the WASM build, regular printf-debugging usually works well enough, or in case of WebGL specific problems there will be validation errors on the JS console from the browser's WebGL implementation).

(disclaimer: sokol author)


I haven't tried it but Chrome dev tools supports debugging C++ compiled to WASM with DWARF debug symbols.


Nice.

Perhaps a level generator based on some ascii art or something would be nice.

That way more people could add levels in merge requests. Or even add a level loader where you can import a list of those levels.


Seems really great, I played all the way through. Here's a couple low-hanging QOL suggestions:

* Use right-click for the camera control, rather than left-click away from the ball. It's unnerving to have the camera change while you're trying to line up a shot.

* Show a shot counter, and assign each hole a par.

* Slightly tune down the friction. I had the ball stop dead on slopes a couple of times, and it stopped way earlier than I expected on slower shots.


After spending my career working in higher level languages, I'm always impressed by what people can do with languages like C. It's not just for drivers anymore.


It used to be the norm to write games in C. In fact it used to be the norm to write them in assembly, C was seen as a higher level abstraction that sped up games development once upon a time.


There's a good Diablo 1 "making of" video, the lead developer talks about learning C while coding the game in assembly. I'll try to find it.


Yeah, I'm pretty sure most game devs of that era were doing something similar. It seems that once games went 3D, it was too impractical to do assembly anymore. So basically a lot of early PS1/N64/Saturn games were likely some pretty rough C code if I had to guess.


It's less that but that the C tooling matured to the point where it was actually good enough to use. Particularly in terms of good enough output. Tight loops and often called functions were and sometimes still are (in SIMD terms) written in assembly so they could be hand optimized.

More exotic hardware also relied on the vendors providing a C compiler and the quality there could vary wildly.


It was never just for drivers. Most of what you use in high-level languages is just syntactical sugar for things that might take three lines in C instead of one line in your usual language.


Three uncorrelated lines, two of which take a buffer, length pair which is also uncorrelated, calling something with undefined behavior if the buffer and length aren't the correct pairing.

But yes.


Putters, too!


Once upon a time such kind of games used to be done in C, after being done several years in Assembly, hardly anything to be amazed.


The main game state machine is a neat read.

https://github.com/mgerdes/Open-Golf/blob/master/src/golf/ga...


After many tries, I finished level 12 in one stroke.

It would be nice to be able to skip the starting animation.


This is excellent. I had a similar (but not as well executed) game on an old Sony-Ericsson phone back in the day, and I spent way to much time playing it. Took me back. Thanks for sharing this!


Cross-platform except for MacOS

https://github.com/mgerdes/Open-Golf/issues/3


Web Inspector on Safari showing failure: "Worker load was blocked by Cross-Origin-Embedder-Policy"


They seem to have a build script for "OSX" but maybe it's just incomplete / work-in-progress? It uses glfw, which I know for sure still runs on Mac because I use it in my own cross-platform graphics projects.


Builds and runs well in Asahi Linux :) Frame rate isn't great without GPU support, but totally playable.


Absolutely crazy that Asahi Linux beats MacOS on even one silly datapoint of compatibility lol. Open source is sick.


TBF, the only reason why macOS isn't currently supported seems to be some minor build system details (e.g. the toplevel CMakeLists.txt file has explicit support for Windows, Linux, Android, iOS and Emscripten, but not macOS).


Looks like that issue has now fixed by the author


Works fine on MacOS on Chrome, just not Safari.


This is excellent. Sokol is so very elegant compared to alternatives.


I'd love to hear more about the lightmapping interpolation for moving objects. I wonder what kinds of efficiencies the author had to find to make it performant.


Nice one - amazing what's possible in a browser today! Also, impressive how lean the code is in terms of the small number of libraries need.


At first I was like: “this is easy!!”

Then suddenly it wasn’t.


Cool project!

Was this inspired by Golf with Your Friends? I've been playing that a fair bit, it's pretty fun and good value.


looks like it doesn't (yet?) have networking support. my fiancée plays GFW almost daily after it was on sale recently, it's a fantastic casual to play both with friends or with strangers online, pretty chill community


Very nice simple golf game. Refreshing on mobile where there's nothing but the game :)


Odd. I couldn't get it to work on Edge, Chrome, or Firefox on Android.


Water hazzard on 7 is fun. Haven't seen that before. To develper -- Nice Job!


This is frustrating. Very realistic and true to what playing golf IRL feels like.


It's great, but the hole is too wide.

The ball shouldn't go in easily if you hit too hard.


Wow, this is neat.


Lots of fun. Then I got to level 12... :)


Quite a lot of fun! Thank you so much.


Very well done!


Extremely playable, nice work!


waiting for the first post that says this should have been written in rust


I'm waiting for the "programming language in the title = clickbait" crowd


They only show up when said language is rust.


Addicted to it.


Love it


Between this, Elden Ring, and my rediscovery of FFXIV, I now firmly believe there's a global conspiracy to stop me from doing a single minute of work.


Hi, have you meet Wordle? :)


I was doing it daily for a while. For some reason the acquisition news made me stop, or maybe it was just the timing. Maybe it's time to get back into the zone.


But Wordle takes what 15 minutes of your day?


It's not just Wordle proper, though, it's all the variants...Nerdle, Worldle, Heardle, Dordle/Quordle/Octordle/etc...


Not even for the average HN user.


Hi, have you meet Semantle? :)


This is wonderful. Thanks for making it.

-- Wanted to share a memory. Growing up there was this put-put course that was called Magic Mountain that my family and I used to go to. It was sort of a big hill that they made into a mountain so that when you were walking on it you felt like you were a giant. Anyway they had this small stream that came down the side of the mountain and wound in-between all of the courses. There was this one hole where the stream intersected at the top of this really obnoxious little course with lots of switchbacks and weird angles. You were "supposed to" (quote on quote) jump the stream and continue on with the hole, but if you managed to knock your ball into the stream there was a ball catch at the bottom that would push the ball back onto the course near the hole so it didn't get washed out to the bottom of the entire mountain. It was possible to make a hole in one if you knocked the ball into the stream - the little river would carry the ball down to the bottom and then gently push it into the hole. Your game reminded me of that memory. Thanks.


Oh, so a Golf with Your Friends clone. neat.


Why "Works best with Chrome?" It works fine for me in Firefox.


Somewhere in Japan a lawyer picks up a pencil https://en.wikipedia.org/wiki/NES_Open_Tournament_Golf




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: