求助:如何在8086 TASM中实现6×6像素图形对象的移动?
Hey there! Let's tackle this bullet problem head-on—since this is your high school final project with a weekend deadline, let's get this sorted out step by step. I've gone through your code and spotted several key issues that are stopping your bullet from moving and causing those weird leftover pixels.
1. Your Bullet Detection Logic Is Targeting the Wrong Pixels
The biggest problem is in your progbullets procedure. Right now, you're checking pixels at X=87, Y=dx (since int 10h function 0Dh uses cx for X and dx for Y), but your left-facing bullet is drawn at Y=87, X=133 (from bulletleft: mov di,320*87+133). You're looking in the wrong place entirely—so your code never finds the red bullet pixel to trigger movement.
Fix for progbullets:
We need to loop through the actual area where your bullet is located (6x6 pixels: Y from 87 to 92, X starting at 133 and moving left). Here's a revised version:
proc progbullets mov bx, [bullet_x_left] ; Load current bullet X position check_left_pixel: mov cx, bx ; X coordinate to check mov dx, 87 ; Starting Y coordinate of the bullet check_y_range: mov ah, 0Dh ; Read pixel function int 10h cmp al, 4 ; Check if it's the red bullet color je move_left_bullet ; Found the bullet—move it inc dx cmp dx, 93 ; Check all 6 Y lines (87 to 92) jne check_y_range dec bx cmp bx, 0 ; Stop if bullet hits left edge jge check_left_pixel jmp exit1 move_left_bullet: ; First, erase the old bullet (draw black over it) mov di, 320*87 + bx lea si, [black_bullet] ; 6x6 array filled with black (0) pixels mov [LineLength], 6 mov [NumOfLines], 6 call DrawPix ; Now draw the bullet one pixel left dec bx mov [bullet_x_left], bx ; Save new X position mov di, 320*87 + bx lea si, [bullet] mov [LineLength], 6 mov [NumOfLines], 6 call DrawPix exit1: ret endp
Note: You'll need to create a black_bullet data array identical to your bullet array but filled with black (0) pixels—this erases the old bullet position so you don't get leftover pixels.
2. Your leftbull Procedure Has Incorrect Position Calculation
Your current leftbull uses mov di,320*84 + dx, which targets Y=84 instead of the bullet's actual Y=87. Plus, you're not erasing the old bullet, which causes those "异常像素" (leftover pixels). The revised code above handles both erasing and correct positioning, so you can replace your existing leftbull with this logic.
3. Control Movement Speed to 4 Pixels Per Second
Right now, your loop runs as fast as possible, which would make the bullet zoom across the screen if it worked. To get a steady 4 pixels per second:
- Use the system timer (
int 1Ah) to trigger a move every 1/4 second (since 18.2 timer ticks = 1 second, ~4.5 ticks per move). - Add a variable to track when the last move happened.
Adjust your main loop like this:
start: mov [bullet_x_left], 133 ; Initialize bullet's starting X mov [last_move_tick], 0 Main_Loop: call keycontrol func_Loop: ; Check if enough time has passed to move the bullet mov ah, 00H int 1Ah sub dx, [last_move_tick] cmp dx, 5 ; ~1/4 second (adjust if needed for speed) jl skip_move ; Update the last move time mov [last_move_tick], dx call progbullets skip_move: ; Keep the loop running jmp func_Loop ; Exit code mov ah,1 int 21h mov ax, 4C00H int 21h
4. Quick Fix for Your bulletleft Procedure
Make sure when you first fire the bullet, you initialize its starting X position:
bulletleft: mov di,320*87+133 mov [bullet_x_left], 133 ; Save starting X coordinate lea si, [bullet] mov [LineLength],6 mov [NumOfLines],6 call DrawPix ret endp
Key Takeaways
- Always erase the old sprite before drawing the new one to avoid leftover pixels.
- Double-check
int 10hcoordinate order:cx = X,dx = Y—it's easy to mix these up! - Use the system timer to control movement speed instead of looping as fast as possible.
I hope this gets your bullet moving smoothly in time for your deadline!
内容的提问来源于stack exchange,提问作者doraviv

