fragglet / sdl-sopwith Goto Github PK
View Code? Open in Web Editor NEWClassic bi-plane shoot-'em up
Home Page: https://fragglet.github.io/sdl-sopwith
License: GNU General Public License v2.0
Classic bi-plane shoot-'em up
Home Page: https://fragglet.github.io/sdl-sopwith
License: GNU General Public License v2.0
In vanilla Sopwith when you complete a level, your remaining planes get counted down and you get rewarded with points - so that there's a bonus if you manage to avoid being shot down. The code that does this is in swrestart()
but it appears to be broken - we do the pause but don't update the screen. And then, we reset the score anyway (#20).
It's confusing to users that the close button doesn't work; it should exit the game.
When I saw the #IFDEF LCD
preprocessor directive in video.c
, I got interested in adding a color palette that similarly replicates my own original experience with Sopwith, except on an amber monochrome CGA monitor.
If it's not too big of a change, I'd like to promote that color palette option from preprocessor directive to full configuration option in the menu.
I roughed together a quick example of what this feature could look like, by adding a new configuration option with a new type:
{"conf_video_palette", CONF_INT, {&conf_video_palette}},
(press the play button to see the colour palette change)
CONF_INT
the best way to do it?The current sound output is deafening and very hard on the ears because it's a square wave. So it's completely understandable that sound got disabled by default. But a better solution would be to apply a filter to make the sound less harsh - sounding like a real PC speaker would arguably be a more accurate representation of the original game anyway
The codebase still depends on SDL 1.2, which is long obsolete. Transitioning to SDL2 should allow several nice enhancements, such as arbitrary window scaling using hardware acceleration.
The original PC speaker timer chip runs at 1.19328 MHz, but the square wave in src/sdl/pcsound.c
is sampled at 48 kHz. This leads to very noticeable aliasing artifacts (it's the DTMF-like sounds accompanying the square waves). This is not how it sounds on original hardware, and it's a bit unpleasant, so I think it's worth fixing.
For maximum accuracy, it should sample the square wave at 1.19328 MHz and then do downsampling to 48 kHz (that entails doing a 24 kHz low-pass filter on the 1.19328 MHz samples and then taking every nth sample at the right ratio -- it's roughly every 25th sample, and you can take averages of adjacent samples to deal with the non-integer ratio between the sampling rates).
However, for good-enough output without needing to do any of that math, instead it can oversample the square wave and take an average.
diff --git a/src/sdl/pcsound.c b/src/sdl/pcsound.c
index ee9180f..743779d 100644
--- a/src/sdl/pcsound.c
+++ b/src/sdl/pcsound.c
@@ -209,8 +209,13 @@ static void snd_callback(void *userdata, Uint8 *stream8, int len)
if (!speaker_on) {
sample = 0;
} else {
- sample = square_wave(current_freq * (i + lasttime)
- / output_freq);
+ // Sample the square wave at close to TIMER_FREQ and downsample using a simple low-pass filter.
+ // This reduces aliasing artifacts.
+ float presample = 0;
+ for (int j = 0; j < 25; j++) {
+ presample += square_wave(current_freq * (i + lasttime + j/25.0) / output_freq);
+ }
+ sample = presample / 25.0;
}
sample = FilterNext(&tinny_filter, sample);
stream[i] = (signed int) (sample * VOLUME);
To my ears, 25 is overkill, and you can get away with 3.
Supposedly a feature of the original DOS versions (there are references to "history buffer", though I've never actually made it work). Besides being a nice feature, being able to record and play back demos could also useful for regression testing.
A nice "stretch goal" would be a mission recorder system with the ability to construct little gameplay videos (see Red Baron's mission recorder feature to understand what I mean)
The idea here is to add a toggle that lets you select between Sopwith 1 and 2's tunes.
Last time I checked it (probably around mid-2023 or a bit later), it was obviously not just a matter of replacing the macro SOPWITH1_TUNE with a variable. I wasn't sure what would be the right approach in case the user changes the tune while it's already playing.
If the window is minimized or resized on a menu screen, we need to redraw the screen to refresh it. This currently doesn't happen.
I've been thinking about the way that toggling the sound is handled. If there's interest, I'd like to explore making these changes:
sopwith.cfg
and add it to the options menuRight now, the title music plays slower than the original matching DOS version.
This experimental change partially resolves the differences, but there may still be precision errors (especially right after starting the program):
diff --git a/src/swsound.c b/src/swsound.c
index 1da8869..d3d68b9 100644
--- a/src/swsound.c
+++ b/src/swsound.c
@@ -607,7 +607,7 @@ void swsndupdate(void)
int thisclock = Timer_GetMS();
if (thisclock > lastclock + 1000 / 18.2) {
- lastclock = thisclock;
+ lastclock += 1000 / 18.2;
soundadj();
}
}
We should save the window size and the display number so that the same window size gets used the next time the game runs.
See here:
Line 859 in ea5b00a
After the first level, the game is made more difficult by having the ground targets shoot back at enemy planes. But the logic only targets the first plane on the level (player 1, the cyan player). This should instead be searching through the object list to find any enemy planes that are in range.
DOS sopwith2 had joystick support and SDL provides the API
The purple heart medal is awarded if you successfully return to base while wounded, regardless of how the plane became wounded. It seems a bit dubious to award it as a result of arguably your own clumsiness, but also sets up a rather perverse incentive where you get rewarded for deliberately damaging your own plane through eg. flying through the ox at the end of the runway. I think we should probably limit it to actual combat damage
See title. Bug since the DOS versions.
I checked both Sopwith 2 and Author's Edition and neither of them reset the score. It seemed that we picked up the current reset-score behavior at some point by mistake.
In novice mode you can't stall the plane, but because of this it's possible to stop the plane in mid-air if travelling slowly enough and the plane is tilted up at a steep angle. This bug doesn't exist in the Network/Author's Edition so must have been introduced at some point in SDL Sopwith's development
To make it easier for non-C people like me to mess around with it.
On macOS I ran
brew install SDL2
sh autogen.sh
make
and run it by double-clicking src/sopwith
.
Medals get awarded only after a successful return to base, which makes sense. However, as soon as you crash the plane a single time and lose a life, you lose all the medals you were awarded. It seems rather harsh. A less harsh approach might be that you keep the medals for the duration of the level; this is consistent with the score, which resets to zero at the start of each new level.
@creichen - through some googling I think you were the original implementer of the medals feature, a long long time ago (it finally made it into a release last year when I revived the project!). Do you have any opinions on changing the behavior?
Apart from simplifying one line of code, this can also resolve a bug (missing sounds + unexpected clicks) when used with SDL 2.0.10. I originally tried running sdl-sopwith with this version, given that it's what you get from Ubuntu 20.04 LTS' repository.
This is probably the impacting SDL commit, which is in 2.0.12: libsdl-org/SDL@aef1ed4
Another commit to mention (albeit not for the bug found by me) is the following one from 2.0.22: libsdl-org/SDL@bf66720
These are the changes applied by me:
diff --git a/src/sdl/pcsound.c b/src/sdl/pcsound.c
index 12edde5..0dfef94 100644
--- a/src/sdl/pcsound.c
+++ b/src/sdl/pcsound.c
@@ -188,7 +188,7 @@ static void snd_callback(void *userdata, Uint8 *stream8, int len)
{
static int lasttime;
static float lastfreq;
- uint16_t *stream = (uint16_t *) stream8;
+ int16_t *stream = (int16_t *) stream8;
float sample;
int i;
@@ -213,7 +213,7 @@ static void snd_callback(void *userdata, Uint8 *stream8, int len)
/ output_freq);
}
sample = FilterNext(&tinny_filter, sample);
- stream[i] = (1 << 15) + (signed int) (sample * VOLUME);
+ stream[i] = (int16_t) (sample * VOLUME);
}
lasttime += len;
@@ -307,7 +307,7 @@ void Speaker_Init(void)
audiospec.samples = 1024;
audiospec.freq = 48000;
- audiospec.format = AUDIO_U16SYS;
+ audiospec.format = AUDIO_S16SYS;
audiospec.channels = 1;
audiospec.callback = &snd_callback;
When the game is over it is supposed to return to the title screen, but because of problems with emscripten's version of longjmp()
it just crashes instead
Just noticed this while playing. Probably got broken by the change in #12.
This is required on Flathub and is consumed by e.g. KDE Discover, GNOME Software, โฆ
https://github.com/wjt/flathub/blob/io.github.fragglet.sdl-sopwith/io.github.fragglet.sdl_sopwith.metainfo.xml is my work-in-progress. It may need revising in light of #16.
I think Debian / Ubuntu have one already so maybe we can steal that?
I'd love to see scores uploaded to an online destination so that, upon loading the game, the reigning top scores are listed.
Support for cmd line args such as -host 23513
(port number) and -join 88.88.88.88:23513
(host:port).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.