What you really need: http://1amstudios.com/2014/12/07/c64-smooth-scrolling/ https://www.c64-wiki.com/wiki/Scrolling * The top 4 bits of $D018 (VM10-VM13) control the base of graphics memory * The bottom 3 bits of $D011 (YSCROLL) and $D016 (XSCROLL) let you delay screen display by 0-7 pixels in either axis * The 4th bit of $D011 (RSEL) and $D016 (CSEL) let you shrink the screen viewport so it's visibly 304x192 pixels (in NTSC) even though the screen memory is still 320x200. VM10-13 lets you establish a double-buffer, you can switch instantly between a front and back buffer by changing $D018. While you are scrolling, you copy the front buffer to the back buffer, offset by 8 horizontal pixels (1 byte) or 4 vertical pixels, then add in new map data on the edge you're scrolling towards. On each frame, you update XSCROLL/YSCROLL by one pixel so the visible screen is moving towards your new screen, then once it's moved all 8/4 pixels, switch to the new buffer. The cost of copying all that graphics memory is expensive, so split it across the 8/4 frames.
痛点为 AI 基于上游原始证据的初步提炼;未包含额外中国市场检索。
在C64 BASIC中实现类似《创世纪》风格的俯视地图滚动视图时,开发者面临的核心痛点是:在BASIC解释器极慢的执行速度下,手动逐像素滚动并更新屏幕缓冲区会导致严重的性能瓶颈。用户原本的任务是创建一个平滑滚动的游戏地图视口,但现有流程中,他们不得不依赖低效的BASIC循环和POKE操作,或者编写复杂的6502汇编代码来手动管理双缓冲、滚动偏移和内存复制。这造成了巨大的开发摩擦:一方面,BASIC代码的优化空间有限,即使使用FOR...TO...STEP等技巧,帧率仍然极低;另一方面,汇编方案虽然高效,但需要深入理解VIC-II芯片的寄存器(如$D011、$D016、$D018)和内存布局,学习曲线陡峭,且代码难以复用。评论中amiga386详细解释了双缓冲和滚动机制,而bonzini指出“大多数杂志上的BASIC游戏都有类似的东西,但需要POKE到内存中启动”,这表明开发者不得不重复造轮子,每次都要手动处理底层细节。这种技术门槛和重复劳动导致开发周期延长,且容易因内存管理错误(如缓冲区切换时机不对)导致画面撕裂或崩溃,最终让许多业余开发者放弃实现平滑滚动,转而采用更简单的静态地图或角色居中移动方案。
External article summary
Explanation of how to create an Ultima-style map view turns into an adventure in C64 BASIC optimisation
External article source
- Article title
- C64 BASIC: Game Map Overhead "Camera View"
- Host
- retrogamecoders.com
Selected HN comments
There's a lot that can be improved in the code, such as just using FOR...TO...STEP would be much faster. In general, this is a routine that is super easy to write in 6502 assembly. Most magazine BASIC games had something like that, with a few such routines that were POKEd in memory at startup. Several were written in a relocatable fashion so that they could be copied easily from one game to the next.
Man does this bring back memories of my old Atari 800 and entering or writing games in BASIC for it. Something extremely nostalgic about that kind of development for some of us.
源数据· Raw Archive
- source
- Hacker News
- upstream_source
- hacker_news
- upstream_item_id
- 48279842
- daily_ranking_item_id
- db9cb42d-e08d-496a-8268-4bb6449779df
- rank_date
- 2026-05-27
- rank
- 10
- name
- C64 Basic: Game Map Overhead “Camera View”
- tagline
- retrogamecoders.com
- votes_count
- 67
- comments_count
- 9
- created_at_on_source
- 2026-05-26T13:47:39.000Z
{
"author": "ibobev",
"hn_item_id": 48279842,
"external_url": "https://retrogamecoders.com/overhead-camera-view/"
}{
"by": "ibobev",
"id": 48279842,
"url": "https://retrogamecoders.com/overhead-camera-view/",
"kids": [
48281281,
48280704,
48284276
],
"time": 1779803259,
"type": "story",
"score": 67,
"title": "C64 Basic: Game Map Overhead “Camera View”",
"descendants": 9
}{
"id": "8f5eafa2-dcd1-48f4-a45a-b6de365ec01d",
"daily_ranking_item_id": "db9cb42d-e08d-496a-8268-4bb6449779df",
"source": "hacker_news",
"external_id": "48279842",
"fetched_at": "2026-05-26T22:01:17.262Z",
"story_raw": {
"by": "ibobev",
"id": 48279842,
"url": "https://retrogamecoders.com/overhead-camera-view/",
"kids": [
48281281,
48280704,
48284276
],
"time": 1779803259,
"type": "story",
"score": 67,
"title": "C64 Basic: Game Map Overhead “Camera View”",
"descendants": 9
},
"stats_raw": {
"time": 1779803259,
"score": 67,
"descendants": 9
},
"aux_raw": {
"external_url": "https://retrogamecoders.com/overhead-camera-view/",
"hn_comment_url": "https://news.ycombinator.com/item?id=48279842",
"normalized_text": null,
"external_article": {
"title": "C64 BASIC: Game Map Overhead \"Camera View\"",
"excerpt": "Explanation of how to create an Ultima-style map view turns into an adventure in C64 BASIC optimisation\n\nGames like Ultima have a classic overhead camera view rather than the moving character view that I have been showing in my retro roguelike . How is that implemented?\n\nJay in the Commodore 64 Ultimate Development & Modifications Facebook group asked :\n\nHere is my answer (which on reflection wasn’t as helpful as it could have been):\n\nThe way to do it with c64 characters is the map defines the whole potential area and the “camera view” is a slice of that starting at x, y of the map.\n\nSo if the map is 100,100 you need x to x+11, for y to y+11 rows.\n\nI’m sure someone has code already if not I can come back with some\n\nRather than leave that as it was, I felt I needed to offer a better solution, plus it is a good challenge to walk through in a blog post, so here we are.\n\nAs I mention briefly in my response, the main mental split is between the “world map” and the visible portion. We are simulating a viewport or portal into the whole, and solutions will involve taking the correct slices out of the bigger version and pasting them onto the game screen.\n\nAnother wrinkle, of course, is howe",
"final_url": "https://retrogamecoders.com/overhead-camera-view/",
"fetched_at": "2026-05-26T22:01:10.795Z",
"description": "Explanation of how to create an Ultima-style map view turns into an adventure in C64 BASIC optimisation"
},
"selected_comments": [
{
"id": 48281281,
"raw": {
"by": "amiga386",
"id": 48281281,
"kids": [
48282052
],
"text": "What you really need:<p><a href=\"http://1amstudios.com/2014/12/07/c64-smooth-scrolling/\" rel=\"nofollow\">http://1amstudios.com/2014/12/07/c64-smooth-scrolling/</a><p><a href=\"https://www.c64-wiki.com/wiki/Scrolling\" rel=\"nofollow\">https://www.c64-wiki.com/wiki/Scrolling</a><p>* The top 4 bits of $D018 (VM10-VM13) control the base of graphics memory<p>* The bottom 3 bits of $D011 (YSCROLL) and $D016 (XSCROLL) let you delay screen display by 0-7 pixels in either axis<p>* The 4th bit of $D011 (RSEL) and $D016 (CSEL) let you shrink the screen viewport so it's visibly 304x192 pixels (in NTSC) even though the screen memory is still 320x200.<p>VM10-13 lets you establish a double-buffer, you can switch instantly between a front and back buffer by changing $D018. While you are scrolling, you copy the front buffer to the back buffer, offset by 8 horizontal pixels (1 byte) or 4 vertical pixels, then add in new map data on the edge you're scrolling towards. On each frame, you update XSCROLL/YSCROLL by one pixel so the visible screen is moving towards your new screen, then once it's moved all 8/4 pixels, switch to the new buffer.<p>The cost of copying all that graphics memory is expensive, so split it across the 8/4 frames.",
"time": 1779810089,
"type": "comment",
"parent": 48279842
},
"body": "What you really need: http://1amstudios.com/2014/12/07/c64-smooth-scrolling/ https://www.c64-wiki.com/wiki/Scrolling * The top 4 bits of $D018 (VM10-VM13) control the base of graphics memory * The bottom 3 bits of $D011 (YSCROLL) and $D016 (XSCROLL) let you delay screen display by 0-7 pixels in either axis * The 4th bit of $D011 (RSEL) and $D016 (CSEL) let you shrink the screen viewport so it's visibly 304x192 pixels (in NTSC) even though the screen memory is still 320x200. VM10-13 lets you establish a double-buffer, you can switch instantly between a front and back buffer by changing $D018. While you are scrolling, you copy the front buffer to the back buffer, offset by 8 horizontal pixels (1 byte) or 4 vertical pixels, then add in new map data on the edge you're scrolling towards. On each frame, you update XSCROLL/YSCROLL by one pixel so the visible screen is moving towards your new screen, then once it's moved all 8/4 pixels, switch to the new buffer. The cost of copying all that graphics memory is expensive, so split it across the 8/4 frames.",
"is_op": false,
"author": "amiga386",
"raw_body": "What you really need:<p><a href=\"http://1amstudios.com/2014/12/07/c64-smooth-scrolling/\" rel=\"nofollow\">http://1amstudios.com/2014/12/07/c64-smooth-scrolling/</a><p><a href=\"https://www.c64-wiki.com/wiki/Scrolling\" rel=\"nofollow\">https://www.c64-wiki.com/wiki/Scrolling</a><p>* The top 4 bits of $D018 (VM10-VM13) control the base of graphics memory<p>* The bottom 3 bits of $D011 (YSCROLL) and $D016 (XSCROLL) let you delay screen display by 0-7 pixels in either axis<p>* The 4th bit of $D011 (RSEL) and $D016 (CSEL) let you shrink the screen viewport so it's visibly 304x192 pixels (in NTSC) even though the screen memory is still 320x200.<p>VM10-13 lets you establish a double-buffer, you can switch instantly between a front and back buffer by changing $D018. While you are scrolling, you copy the front buffer to the back buffer, offset by 8 horizontal pixels (1 byte) or 4 vertical pixels, then add in new map data on the edge you're scrolling towards. On each frame, you update XSCROLL/YSCROLL by one pixel so the visible screen is moving towards your new screen, then once it's moved all 8/4 pixels, switch to the new buffer.<p>The cost of copying all that graphics memory is expensive, so split it across the 8/4 frames.",
"created_at": 1779810089,
"reply_count": 1
},
{
"id": 48280704,
"raw": {
"by": "bonzini",
"id": 48280704,
"text": "There's a lot that can be improved in the code, such as just using FOR...TO...STEP would be much faster.<p>In general, this is a routine that is super easy to write in 6502 assembly. Most magazine BASIC games had something like that, with a few such routines that were POKEd in memory at startup. Several were written in a relocatable fashion so that they could be copied easily from one game to the next.",
"time": 1779807322,
"type": "comment",
"parent": 48279842
},
"body": "There's a lot that can be improved in the code, such as just using FOR...TO...STEP would be much faster. In general, this is a routine that is super easy to write in 6502 assembly. Most magazine BASIC games had something like that, with a few such routines that were POKEd in memory at startup. Several were written in a relocatable fashion so that they could be copied easily from one game to the next.",
"is_op": false,
"author": "bonzini",
"raw_body": "There's a lot that can be improved in the code, such as just using FOR...TO...STEP would be much faster.<p>In general, this is a routine that is super easy to write in 6502 assembly. Most magazine BASIC games had something like that, with a few such routines that were POKEd in memory at startup. Several were written in a relocatable fashion so that they could be copied easily from one game to the next.",
"created_at": 1779807322,
"reply_count": 0
},
{
"id": 48284276,
"raw": {
"by": "pugworthy",
"id": 48284276,
"text": "Man does this bring back memories of my old Atari 800 and entering or writing games in BASIC for it. Something extremely nostalgic about that kind of development for some of us.",
"time": 1779821944,
"type": "comment",
"parent": 48279842
},
"body": "Man does this bring back memories of my old Atari 800 and entering or writing games in BASIC for it. Something extremely nostalgic about that kind of development for some of us.",
"is_op": false,
"author": "pugworthy",
"raw_body": "Man does this bring back memories of my old Atari 800 and entering or writing games in BASIC for it. Something extremely nostalgic about that kind of development for some of us.",
"created_at": 1779821944,
"reply_count": 0
}
],
"presentation_fields": {
"title": "C64 Basic: Game Map Overhead “Camera View”",
"tagline": "retrogamecoders.com",
"website_url": "https://retrogamecoders.com/overhead-camera-view/",
"canonical_url": "https://news.ycombinator.com/item?id=48279842"
},
"external_url_hostname": "retrogamecoders.com",
"selected_comments_raw": [
{
"by": "amiga386",
"id": 48281281,
"kids": [
48282052
],
"text": "What you really need:<p><a href=\"http://1amstudios.com/2014/12/07/c64-smooth-scrolling/\" rel=\"nofollow\">http://1amstudios.com/2014/12/07/c64-smooth-scrolling/</a><p><a href=\"https://www.c64-wiki.com/wiki/Scrolling\" rel=\"nofollow\">https://www.c64-wiki.com/wiki/Scrolling</a><p>* The top 4 bits of $D018 (VM10-VM13) control the base of graphics memory<p>* The bottom 3 bits of $D011 (YSCROLL) and $D016 (XSCROLL) let you delay screen display by 0-7 pixels in either axis<p>* The 4th bit of $D011 (RSEL) and $D016 (CSEL) let you shrink the screen viewport so it's visibly 304x192 pixels (in NTSC) even though the screen memory is still 320x200.<p>VM10-13 lets you establish a double-buffer, you can switch instantly between a front and back buffer by changing $D018. While you are scrolling, you copy the front buffer to the back buffer, offset by 8 horizontal pixels (1 byte) or 4 vertical pixels, then add in new map data on the edge you're scrolling towards. On each frame, you update XSCROLL/YSCROLL by one pixel so the visible screen is moving towards your new screen, then once it's moved all 8/4 pixels, switch to the new buffer.<p>The cost of copying all that graphics memory is expensive, so split it across the 8/4 frames.",
"time": 1779810089,
"type": "comment",
"parent": 48279842
},
{
"by": "bonzini",
"id": 48280704,
"text": "There's a lot that can be improved in the code, such as just using FOR...TO...STEP would be much faster.<p>In general, this is a routine that is super easy to write in 6502 assembly. Most magazine BASIC games had something like that, with a few such routines that were POKEd in memory at startup. Several were written in a relocatable fashion so that they could be copied easily from one game to the next.",
"time": 1779807322,
"type": "comment",
"parent": 48279842
},
{
"by": "pugworthy",
"id": 48284276,
"text": "Man does this bring back memories of my old Atari 800 and entering or writing games in BASIC for it. Something extremely nostalgic about that kind of development for some of us.",
"time": 1779821944,
"type": "comment",
"parent": 48279842
}
]
},
"selection_meta": {
"discussion_depth": "top_comments_v1",
"external_article": {
"status": "ok",
"final_url": "https://retrogamecoders.com/overhead-camera-view/",
"status_code": 200,
"content_type": "text/html; charset=utf-8",
"failure_reason": null
},
"snapshot_version": "hn_story_v3",
"selected_comments_count": 3,
"external_article_resolved": true,
"text_normalization_applied": false
},
"created_at": "2026-05-26T22:01:17.546Z",
"updated_at": "2026-05-26T22:01:17.546Z"
}