nes: added road, tint demo; extra tools; embed.html fetch remote url

This commit is contained in:
Steven Hugg 2019-04-26 15:38:34 -04:00
parent 0e47e7d035
commit fe1e0fc9aa
28 changed files with 407 additions and 113 deletions

View File

@ -103,6 +103,7 @@ TODO:
- per-View keyboard shortcuts
- parse labels
- parse .incbin directives?
- can't replace in hex directives
- crt0.s compiled each time?
- debug highlight doesn't go away when debugging -> running
- show breakpoint of PC or highest address on stack
@ -124,6 +125,7 @@ TODO:
- CPU debugging
- disassemble more code around breakpoint
- single-stepping vector games makes screen fade
- break on stack overflow, bad op, bad access, etc
WEB WORKER FORMAT

View File

@ -83,6 +83,14 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
<a tabindex="-1" href="#">Tools</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" target="_8bws_tools" href="./tools/fontgen/">Bitmap Font Generator</a></li>
<li><a class="dropdown-item" target="_8bws_tools" href="http://tomeko.net/online_tools/file_to_hex.php?lang=en">Binary File to Hex Converter</a></li>
<li class="dropdown dropdown-submenu">
<a tabindex="-1" href="#">Atari 2600/VCS</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" target="_8bws_tools" href="https://alienbill.com/2600/playerpalnext.html">playerpal 2600</a></li>
<li><a class="dropdown-item" target="_8bws_tools" href="https://alienbill.com/2600/playfieldpal.html">playfieldpal 2600</a></li>
</ul>
</li>
</ul>
</li>
<hr>

View File

@ -26,10 +26,10 @@ Start:
lda #$1c ; $1C = light blue color
sta PPU_DATA ; $1C -> PPU data
; activate PPU graphics
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
lda #MASK_COLOR
sta PPU_MASK ; enable rendering
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
.endless
jmp .endless ; endless loop

View File

@ -28,10 +28,10 @@ Start:
sta PPU_SCROLL
sta PPU_SCROLL ; PPU scroll = $0000
; activate PPU graphics
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
lda #MASK_BG
sta PPU_MASK ; enable rendering
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
.endless
jmp .endless ; endless loop

View File

@ -30,10 +30,10 @@ Start:
sta PPU_SCROLL
sta PPU_SCROLL ; scroll = $0000
; activate PPU graphics
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
lda #MASK_BG
sta PPU_MASK ; enable rendering
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
.endless
jmp .endless ; endless loop

View File

@ -34,10 +34,10 @@ Start:
sta PPU_ADDR ;PPU addr = 0
sta PPU_SCROLL
sta PPU_SCROLL ;scroll = 0
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
lda #MASK_BG|MASK_SPR
sta PPU_MASK ; enable rendering
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
.endless
jmp .endless ;endless loop

View File

@ -29,10 +29,10 @@ Start:
sta PPU_ADDR ;PPU addr = 0
sta PPU_SCROLL
sta PPU_SCROLL ;scroll = 0
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
lda #MASK_BG|MASK_SPR
sta PPU_MASK ; enable rendering
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
.endless
jmp .endless ;endless loop

View File

@ -287,6 +287,10 @@ void __fastcall__ nmi_set_callback(void (*callback)(void));
#define MASK_BG 0x08
#define MASK_EDGE_SPR 0x04
#define MASK_EDGE_BG 0x02
#define MASK_TINT_RED 0x20
#define MASK_TINT_BLUE 0x40
#define MASK_TINT_GREEN 0x80
#define MASK_MONO 0x01
#define NAMETABLE_A 0x2000
#define NAMETABLE_B 0x2400

View File

@ -12,8 +12,6 @@ extern const byte climbr_title_rle[];
// link title screen palette and RLE nametable
//#link "climbr_title.s"
void fade_in() {
byte vb;
for (vb=0; vb<=4; vb++) {

View File

@ -5,6 +5,8 @@
seg.u ZEROPAGE
org $0
Ptr1 .word ; for temporary pointer storage
TrackFrac .byte ; fractional position along track
Speed .byte ; speed of car
@ -24,9 +26,8 @@ ZOfs .byte ; counter to draw striped center line
Weather .byte ; bitmask for weather
Heading .word ; sky scroll pos.
XCenter = 128
NumRoadSegments = 28
NumRoadScanlines = 112
NumRoadSegments = 56
; Preprocessing result: X positions for all track segments
RoadX0 ds NumRoadSegments
@ -43,7 +44,7 @@ InitialSpeed equ 10 ; starting speed
;;;;; NES CARTRIDGE HEADER
NES_HEADER 0,2,1,0 ; mapper 0, 2 PRGs, 1 CHR, horiz. mirror
NES_HEADER 0,2,1,1 ; mapper 0, 2 PRGs, 1 CHR, vert mirror
;;;;; START OF CODE
@ -53,7 +54,6 @@ Start:
jsr ClearRAM ; clear RAM
jsr WaitSync ; wait for VSYNC (and PPU warmup)
jsr SetPalette ; set palette colors
jsr FillVRAM ; set PPU video RAM
jsr RoadSetup
@ -63,10 +63,10 @@ Start:
sta PPU_ADDR ; PPU addr = $0000
sta PPU_SCROLL
sta PPU_SCROLL ; scroll = $0000
lda #MASK_BG|MASK_SPR|MASK_BG_CLIP
sta PPU_MASK ; enable rendering (first!)
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
lda #MASK_BG|MASK_SPR
sta PPU_MASK ; enable rendering
.endless
jmp .endless ; endless loop
@ -249,43 +249,43 @@ GenTrack subroutine
; fill video RAM
FillVRAM: subroutine
txa
ldy #$20
sty PPU_ADDR
sta PPU_ADDR
ldy #$10
PPU_SETADDR $2000
lda #<RoadTables
sta Ptr1
lda #>RoadTables
sta Ptr1+1
ldx #8
ldy #0
.loop:
lda (Ptr1),y
sta PPU_DATA
adc #7
inx
iny
bne .loop
dey
inc Ptr1+1
dex
bne .loop
rts
; set palette colors
SetPalette: subroutine
ldy #$00
lda #$3f
sta PPU_ADDR
sty PPU_ADDR
ldx #32
PPU_SETADDR $3f00
ldx #16
.loop:
lda Palette,y
sta PPU_DATA
iny
dex
dex
bne .loop
rts
; set sprite 0
SetSprite0: subroutine
sta $200 ;y
lda #1 ;code
sta $200 ;ypos
lda #$00 ;code
sta $201
lda #0 ;flags
lda #$20 ;flags
sta $202
lda #8 ;xpos
lda #$fe ;xpos
sta $203
rts
@ -314,18 +314,26 @@ SetSprite0: subroutine
ENDM
NMIHandler: subroutine
; save registers
SAVE_REGS
; setup sky scroll
lda Heading+1
sta PPU_SCROLL
lda #0
sta PPU_SCROLL
; load sprites
lda #112
; cycle palette colors
lda TPos ; track position
lsr ; / 2
and #16 ; now either 0 or 16
tay ; Y is palette offset
jsr SetPalette ; call SetPalette
PPU_SETADDR $2000 ; reset PPU address
; load sprite zero
lda #109
jsr SetSprite0
lda #$02
sta PPU_OAM_DMA
; do road calc
; setup sky scroll
lda Heading+1
sta PPU_SCROLL ; X scroll
lda #0
sta PPU_SCROLL ; Y scroll = 0
; do road calculations
jsr RoadPreSetup
jsr PreprocessCurve
jsr RoadPostFrame
@ -337,30 +345,42 @@ NMIHandler: subroutine
; alter horiz. scroll position for each scanline
ldy #0
.loop
; pad out rest of scanline
SLEEP 78
; change scroll register
tya
lsr
lsr
lsr ; / 2
tax
lda RoadX0,x
lda RoadX0,x ; get X offset of scanline
eor #$80 ; + 128
sta PPU_SCROLL ; horiz byte
lda #0
sta PPU_SCROLL ; vert byte
SLEEP 84
sta PPU_SCROLL ; vert byte = 0
; take extra cycle every 4th line
tya
and #3
bne .skipcyc
.skipcyc
; next loop iteration
iny
cpy #112
bne .loop
cpy #NumRoadScanlines
bne .loop ; do next scanline
; restore registers and return from interrupt
RESTORE_REGS
rti
;;;;; CONSTANT DATA
align $100
;;{pal:"nes",layout:"nes"};;
Palette:
hex 1f ;background
hex 09092c00 ;bg0
hex 09091900 ;bg1
hex 09091500 ;bg2
hex 09092500 ;bg3
hex 0F3F06300F19063F0F1916063F180801
hex 0F30163F0F19163F0F1906160F180801
;;
RoadTables:
incbin "road/nametable.dat"
incbin "road/attribute.dat"
incbin "road/nametable1.dat"
incbin "road/attribute1.dat"
;;;;; CPU VECTORS
@ -369,4 +389,4 @@ Palette:
;;;;; TILE SETS
org $10000
incbin "jroatch.chr"
incbin "road/road.chr"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
presets/nes/road/road.chr Normal file

Binary file not shown.

View File

@ -5,6 +5,8 @@
seg.u ZEROPAGE
org $0
SkipY ds 1
;;;;; OTHER VARIABLES
@ -34,10 +36,10 @@ Start:
sta PPU_ADDR ; PPU addr = $0000
sta PPU_SCROLL
sta PPU_SCROLL ; scroll = $0000
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
lda #MASK_BG|MASK_SPR
sta PPU_MASK ; enable rendering
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
.endless
jmp .endless ; endless loop
@ -69,7 +71,7 @@ SetPalette: subroutine
; set sprite 0
SetSprite0: subroutine
sta $200 ;y
lda #$01 ;code
lda #$a0 ;code
sta $201
lda #$20 ;flags
sta $202
@ -100,6 +102,13 @@ NMIHandler: subroutine
bvc .wait1
ldy #0
.loop
; take out cycle every 4th line
tya
and #3
bne .skipcyc ; clks = 2/3/3/3
.skipcyc
; pad out rest of scanline
SLEEP 65
; alter horiz. scroll position for each scanline
tya
sec
@ -111,10 +120,9 @@ NMIHandler: subroutine
sta PPU_SCROLL ; horiz byte
lda #0
sta PPU_SCROLL ; vert byte
; pad out rest of scanline
SLEEP 72
; next iteration of loop
iny
cpy #224
cpy #112
bne .loop
RESTORE_REGS
rti

View File

@ -1,16 +1,45 @@
#include <stdlib.h>
#include <string.h>
// include NESLIB header
#include "neslib.h"
// link the pattern table into CHR ROM
//#link "chr_generic.s"
/*{pal:"nes",layout:"nes"}*/
const char PALETTE[32] = {
0x03, // screen color
0x11,0x30,0x27,0x0, // background palette 0
0x1c,0x20,0x2c,0x0, // background palette 1
0x00,0x10,0x20,0x0, // background palette 2
0x06,0x16,0x26,0x0, // background palette 3
0x16,0x35,0x24,0x0, // sprite palette 0
0x00,0x37,0x25,0x0, // sprite palette 1
0x0d,0x2d,0x3a,0x0, // sprite palette 2
0x0d,0x27,0x2a // sprite palette 3
};
// setup PPU and tables
void setup_graphics() {
// clear sprites
oam_clear();
// set palette colors
pal_all(PALETTE);
}
void main(void)
{
pal_col(1,0x04);
pal_col(2,0x20);
pal_col(3,0x30);
setup_graphics();
// draw message
vram_adr(NTADR_A(2,2));
vram_write("HELLO, WORLD!", 12);
ppu_on_all();//enable rendering
while(1);//do nothing, infinite loop
// enable rendering
ppu_on_all();
// infinite loop
while(1) {
}
}

69
presets/nes/tint.c Normal file
View File

@ -0,0 +1,69 @@
#include <stdlib.h>
#include <string.h>
// include NESLIB header
#include "neslib.h"
// link the pattern table into CHR ROM
//#link "chr_generic.s"
/*{pal:"nes",layout:"nes"}*/
const char PALETTE[32] = {
0x2D, // screen color
0x00,0x30,0x30,0x00, // background palette 0
0x0C,0x20,0x2C,0x00, // background palette 1
0x14,0x10,0x25,0x00, // background palette 2
0x17,0x16,0x28,0x00, // background palette 3
0x16,0x35,0x24,0x00, // sprite palette 0
0x00,0x37,0x25,0x00, // sprite palette 1
0x0D,0x2D,0x3A,0x00, // sprite palette 2
0x0D,0x27,0x2A // sprite palette 3
};
// setup PPU and tables
void setup_graphics() {
// clear sprites
oam_clear();
// set palette colors
pal_all(PALETTE);
}
void main(void)
{
byte i;
setup_graphics();
// draw message
for (i=0; i<30; i++) {
vram_adr(NTADR_A(1,i));
// vram_write("\x18\x18 USE CONTROLLER FOR TINT \x18\x18\x18", 30);
vram_write(" A:red B:green \x1e\x1f:blue \x1c\x1d:mono", 30);
}
// attributes
vram_adr(0x23c0);
vram_fill(0x00, 8);
vram_fill(0x55, 8);
vram_fill(0xaa, 8);
vram_fill(0xff, 8);
vram_fill(0x11, 8);
vram_fill(0x33, 8);
vram_fill(0xdd, 8);
// enable rendering
ppu_on_all();
// infinite loop
while(1) {
byte pad = pad_poll(0);
byte mask = MASK_BG;
if (pad & PAD_A)
mask |= MASK_TINT_RED;
if (pad & PAD_B)
mask |= MASK_TINT_GREEN;
if (pad & (PAD_LEFT|PAD_RIGHT))
mask |= MASK_TINT_BLUE;
if (pad & (PAD_UP|PAD_DOWN))
mask |= MASK_MONO;
ppu_mask(mask);
}
}

View File

@ -34,10 +34,10 @@ Start:
sta PPU_ADDR ; PPU addr = $0000
sta PPU_SCROLL
sta PPU_SCROLL ; scroll = $0000
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
lda #MASK_BG|MASK_SPR
sta PPU_MASK ; enable rendering
lda #CTRL_NMI
sta PPU_CTRL ; enable NMI
.endless
jmp .endless ; endless loop
@ -93,26 +93,26 @@ NMIHandler: subroutine
; load sprites
lda #$02
sta PPU_OAM_DMA
; wait for sprite 0
.wait0 bit PPU_STATUS
bvs .wait0
.wait1 bit PPU_STATUS
bvc .wait1
; set XY scroll
; compute first PPU_ADDR write
; compute second PPU_ADDR write
lda ScrollX
tax
tax ; ScrollX -> X
lsr
lsr
lsr
sta Temp
lda ScrollY
tay
and #$f8
tay ; ScrollY -> Y
and #$38
asl
asl
ora Temp
pha
ora Temp ; (ScrollX >> 3) | ((ScrollY & 0x38) << 2)
pha ; push onto stack
; wait for sprite 0
.wait0 bit PPU_STATUS
bvs .wait0
.wait1 bit PPU_STATUS
bvc .wait1
; set PPU_ADDR.1
lda #0
sta PPU_ADDR

View File

@ -3,7 +3,7 @@ window['Javatari'].AUTO_START = false;
import { PLATFORMS } from "./emu";
import { Platform } from "./baseplatform";
import { stringToByteArray } from "./util";
import { stringToByteArray, getWithBinary } from "./util";
export var platform_id : string; // platform ID string
export var platform : Platform; // platform object
@ -67,17 +67,37 @@ function addPageFocusHandlers() {
});
}
function startROM(title, rom) {
if (!rom ) {
alert("No ROM found.");
return;
}
console.log(rom.length + ' bytes');
platform.loadROM(title, rom);
platform.resume();
}
function startPlatform(qs) {
if (!PLATFORMS[platform_id]) throw Error("Invalid platform '" + platform_id + "'.");
platform = new PLATFORMS[platform_id]($("#emulator")[0]);
platform.start();
var title = qs['n'] || 'Game';
var rom : Uint8Array;
var romurl = qs['url'];
var lzgvar = qs['r'];
var lzgrom = stringToByteArray(atob(lzgvar));
var rom = new lzgmini().decode(lzgrom);
console.log(rom.length + ' bytes');
platform.loadROM(title, rom);
platform.resume();
if (romurl) {
// load rom url remotely
console.log(romurl);
getWithBinary(romurl, (data) => {
startROM(title, data);
}, 'arraybuffer');
return true;
} else if (lzgvar) {
// decompress from lzg
var lzgrom = stringToByteArray(atob(lzgvar));
rom = new lzgmini().decode(lzgrom);
}
startROM(title, rom);
return true;
}

View File

@ -16,6 +16,7 @@ const JSNES_PRESETS = [
{id:'metasprites.c', name:'Metasprites'},
{id:'flicker.c', name:'Flickering Sprites'},
{id:'metacursor.c', name:'Controllers'},
{id:'tint.c', name:'Color Emphasis'},
{id:'rletitle.c', name:'Title Screen RLE'},
{id:'statusbar.c', name:'Split Status Bar'},
{id:'horizmask.c', name:'Offscreen Scrolling'},
@ -34,8 +35,9 @@ const JSNES_PRESETS = [
{id:'ex3.asm', name:'Sprite Demo (ASM)'},
{id:'ex4.asm', name:'Controller Demo (ASM)'},
{id:'musicdemo.asm', name:'Famitone Demo (ASM)'},
{id:'scrollrt.asm', name:'Line-by-line Scrolling (ASM)'},
{id:'xyscroll.asm', name:'XY Split Scrolling (ASM)'},
{id:'scrollrt.asm', name:'Line-by-line Scrolling (ASM)'},
{id:'road.asm', name:'3-D Road Demo (ASM)'},
];
/// JSNES

View File

@ -1,7 +1,7 @@
"use strict";
import { FileData, Dependency, SourceLine, SourceFile, CodeListing, CodeListingMap, WorkerError, Segment, WorkerResult } from "./workertypes";
import { getFilenameForPath, getFilenamePrefix, getFolderForPath, isProbablyBinary } from "./util";
import { getFilenamePrefix, getFolderForPath, isProbablyBinary } from "./util";
type BuildResultCallback = (result:WorkerResult) => void;
type BuildStatusCallback = (busy:boolean) => void;
@ -153,7 +153,7 @@ export class CodeProject {
this.preloadWorker(this.mainpath);
var msg = {updates:[], buildsteps:[]};
// TODO: add preproc directive for __MAINFILE__
var mainfilename = getFilenameForPath(this.mainpath);
var mainfilename = this.stripLocalPath(this.mainpath);
var maintext = this.getFile(this.mainpath);
var depfiles = [];
msg.updates.push({path:mainfilename, data:maintext});
@ -177,10 +177,10 @@ export class CodeProject {
// TODO: get local file as well as presets?
loadFiles(paths:string[], callback:LoadFilesCallback) {
var result : Dependency[] = [];
function addResult(path, data) {
var addResult = (path, data) => {
result.push({
path:path,
filename:getFilenameForPath(path),
filename:this.stripLocalPath(path),
link:true,
data:data
});
@ -319,7 +319,7 @@ export class CodeProject {
// returns first listing in format [prefix].lst (TODO: could be better)
getListingForFile(path) : CodeListing {
var fnprefix = getFilenamePrefix(getFilenameForPath(path));
var fnprefix = getFilenamePrefix(this.stripLocalPath(path));
var listings = this.getListings();
for (var lstfn in listings) {
if (getFilenamePrefix(lstfn) == fnprefix) {
@ -327,4 +327,15 @@ export class CodeProject {
}
}
}
stripLocalPath(path : string) : string {
// TODO: strip main path as well
if (path.startsWith('local/')) {
path = path.substring(6);
}
if (path.startsWith('share/')) {
path = path.substring(6);
}
return path;
}
}

View File

@ -12,7 +12,7 @@ import { PLATFORMS, EmuHalt, Toolbar } from "./emu";
import * as Views from "./views";
import { createNewPersistentStore } from "./store";
import { getFilenameForPath, getFilenamePrefix, highlightDifferences, invertMap, byteArrayToString, compressLZG,
byteArrayToUTF8, isProbablyBinary } from "./util";
byteArrayToUTF8, isProbablyBinary, getWithBinary } from "./util";
import { StateRecorderImpl } from "./recorder";
// external libs (TODO)
@ -101,22 +101,6 @@ function setLastPreset(id:string) {
}
}
// firefox doesn't do GET with binary files
function getWithBinary(url:string, success:(text:FileData)=>void, datatype:'text'|'arraybuffer') {
var oReq = new XMLHttpRequest();
oReq.open("GET", url, true);
oReq.responseType = datatype;
oReq.onload = function (oEvent) {
if (oReq.status == 200)
success(oReq.response);
else if (oReq.status == 404)
success(null);
else
throw "Error " + oReq.status + " loading " + url;
}
oReq.send(null);
}
function initProject() {
current_project = new CodeProject(newWorker(), platform_id, platform, store);
projectWindows = new ProjectWindows($("#workspace")[0] as HTMLElement, current_project);

View File

@ -320,7 +320,7 @@ export function isProbablyBinary(path:string, data?:number[] | Uint8Array) : boo
// check extensions
if (path) {
path = path.toUpperCase();
const BINEXTS = ['.CHR','.BIN','.PAL','.NAM','.RLE','.LZ4'];
const BINEXTS = ['.CHR','.BIN','.DAT','.PAL','.NAM','.RLE','.LZ4'];
for (var ext of BINEXTS) {
if (path.endsWith(ext)) score++;
}
@ -446,3 +446,25 @@ export function rle_unpack(src : Uint8Array) : Uint8Array {
}
return new Uint8Array(dest);
}
// firefox doesn't do GET with binary files
export function getWithBinary(url:string, success:(text:string|Uint8Array)=>void, datatype:'text'|'arraybuffer') {
var oReq = new XMLHttpRequest();
oReq.open("GET", url, true);
oReq.responseType = datatype;
oReq.onload = function (oEvent) {
if (oReq.status == 200) {
var data = oReq.response;
if (data instanceof ArrayBuffer) {
data = new Uint8Array(data);
}
success(data);
} else if (oReq.status == 404) {
success(null);
} else {
throw "Error " + oReq.status + " loading " + url;
}
}
oReq.send(null);
}

View File

@ -342,6 +342,15 @@ function populateEntry(fs, path:string, entry:FileEntry, options:BuildOptions) {
var data = entry.data;
if (options && options.processFn)
data = options.processFn(data);
// create subfolders
var toks = path.split('/');
if (toks.length > 1) {
for (var i=0; i<toks.length-1; i++)
try {
fs.mkdir(toks[i]);
} catch (e) { }
}
// write file
fs.writeFile(path, data, {encoding:entry.encoding});
fs.utime(path, entry.ts, entry.ts);
console.log("<<<", path, entry.data.length);

6
tools/nes/Makefile Normal file
View File

@ -0,0 +1,6 @@
nametable.dat: road.png
makechr -e error.png $< #-b 0000ff
road.png: road.py
python road.py

102
tools/nes/road.py Executable file
View File

@ -0,0 +1,102 @@
#!/usr/bin/python
# Import a library of functions called 'pygame'
import pygame
import random
from math import pi
# Initialize the game engine
pygame.init()
# Define the colors we will use in RGB format
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
BLUE = ( 0, 0, 255)
GREEN = ( 0, 184, 0)
CURBING = [
(136,20,0),
(168,16,0),
]
CENLINE = [
(124,124,124),
(188,188,188),
]
MOUNTAINS = [
(80,48,0),
(172,124,0)
]
# Set the height and width of the screen
size = [512, 240]
y0 = 112
x0 = 256
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Example code for the draw module")
#Loop until the user clicks the close button.
done = False
clock = pygame.time.Clock()
while not done:
# This limits the while loop to a max of 10 times per second.
# Leave this out and we will use all CPU we can.
clock.tick(10)
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
done=True # Flag that we are done so we exit this loop
# All drawing code happens after the for loop and but
# inside the main while done==False loop.
# Clear the screen and set the screen background
screen.fill(BLUE)
pygame.draw.rect(screen, GREEN, [0, y0, 512, 240-y0])
# draw the road
for y in range(y0,240):
i = y-y0
rw = i*2
cw = rw/4
lw = rw/32
z = 500.0/(i+1)
curbcol = CURBING[int(z) % 2]
cencol = CENLINE[int(z) % 2]
if i < 16:
cencol = BLACK #CENLINE[0]
if i < 0:
curbcol = BLACK #CURBING[0]
pygame.draw.line(screen, BLACK, [x0-rw, y], [x0+rw, y], 1)
pygame.draw.line(screen, curbcol, [x0-rw-cw, y], [x0-rw, y], 1)
pygame.draw.line(screen, curbcol, [x0+rw, y], [x0+rw+cw, y], 1)
pygame.draw.line(screen, cencol, [x0-rw/3-lw, y], [x0-rw/3+lw, y], 1)
pygame.draw.line(screen, cencol, [x0+rw/3-lw, y], [x0+rw/3+lw, y], 1)
# draw mountains
h1 = 1
h2 = 2
for x in range(0,512):
pygame.draw.line(screen, MOUNTAINS[0], [x, y0-1], [x, y0-h1], 1)
pygame.draw.line(screen, MOUNTAINS[1], [x, y0-1], [x, y0-h2], 1)
if random.randint(0,8) > h1:
h1 += 1
elif h1 > 1:
h1 -= 1
if random.randint(0,6) > h2:
h2 += 1
elif h2 > 1:
h2 -= 1
# Go ahead and update the screen with what we've drawn.
# This MUST happen after all the other drawing commands.
pygame.display.flip()
pygame.image.save(screen, 'road.png')
# Be IDLE friendly
pygame.quit()