精华内容
下载资源
问答
  • 像素游戏-源码

    2021-02-25 20:42:47
    像素游戏 你好! 这是指导。
  • 像素游戏网页特效

    2019-10-04 23:58:52
    像素游戏网页特效
  • 全套的克鲁赛德战记游戏素材,包括人物精灵、立绘、背景音乐、技能特效等;精美的画质是学习像素画与游戏开发测试的首选
  • pixsynt:像素游戏-源码

    2021-03-19 05:03:14
    象素
  • 星际之门像素战争 由我在 Unity 上制作的基于星际之门的像素艺术 2D 游戏
  • 超级好用的像素游戏工具 可以点击我的blog,里面有具体文档 抽空会写一个教程之类的
  • 一款Android的像素游戏

    2018-08-29 13:32:23
    像素风格的Android游戏,纯Java实现.简洁有力.非常适合学习.
  • 随着分辨率的普遍提高,我们已经告别了依赖于简陋像素来表现游戏画面的年代。但还是有不少人像我一样沉迷于像素美术和游戏。如今到处可以都可以看到的各式像素作品,虽然大多被直接称呼为像素画,但实际上已经分化为...

    转自:http://fushigi-hako.site/2017/07/02/from_pixel_to_screen_1/

    无所不在的像素画

    分类

    随着分辨率的普遍提高,我们已经告别了依赖于简陋像素来表现游戏画面的年代。但还是有不少人像我一样沉迷于像素美术和游戏。如今到处可以都可以看到的各式像素作品,虽然大多被直接称呼为像素画,但实际上已经分化为很多分支,简单的将其归类为像素作品未免太含糊。在开始正文之前我先将他们粗粗的分个类。一些比较常见的代表如:

    1. 大颗粒像素,此类像素作品一般细节较少,人物符号化或者抽象化。同时还可能出现非像素元素,如光晕,渐变

      2.粒度较小的像素画,主要还是色块化,边缘并没有强化。

      3.强化边缘和高光,细节丰富,但是普遍尺寸较小。

    另外,在一些UI图标的绘制过程中,由于图标较小,也同样采用像素点绘的方式。因为它平时也不会被称为像素画,所以这里也不讨论。

    其中第3种是我在本文中将着重讨论的。
    这类像素图可能和平时所提到的像素图差的最远,因为它并不是为了做出像素化效果而诞生的。相反它是游戏机在分辨率和色板支持加强之后的产物(光是从GB到GBC,支持的色深就从2位变成了15位)。在这方面,任天堂算是是做到了极致(也可能因为任天堂的主机的屏幕天生小的缘故)这类像素画在抗锯齿(伪),光照,色彩的调和的方面很有特点(这篇文章中不细说)

    再现像素画

    就GBA而言,分辨率为240 *160,但我们现在再制作像素的游戏时,玩家一定不会接受在这么小的一个屏幕上去玩游戏。一个是因为眼睛看的太累(长大后眼睛都变差了…)。另一方面,考虑到像素画的成本,也不建议针对一个1080p的屏幕进行逐像素绘画。为了满足一些玩家想要的像素的效果,一个最简单直接的方法就是将画面放大。

    虽然这种方法省时省力,但是也会带来一个问题。在绘制像素画中的曲线时,由于一般不对线条使用反走样(会让画面变脏)来抗锯齿。在分辨率较低的时候,像素的边缘可以帮助人们识别且很难注意到异样,但当画面放大后,这些边缘就会显得粗糙不堪。这也是像素画风被一些人所诟病的原因。

    为此,包括ppsspp在内的模拟器中,会内置不少shader来对图像进行后期处理。对于2D图像来说,具体方法包括xBRZ等滤镜来平滑放大图像(xBRZ对2D像素放大会产生平滑而舒适的效果,但是这会损失像素的特征),增加crt, 扫描线等后期特效将像素画做旧。当然,你也可以利用物理的手段将信号输出到CRT屏幕上,参考这里
    另外,这篇文章 中讲述了一些crt效果的来源,也讨论了很多细节问题。一个简单的对比图:

    常见的效果如下

    虽然实现方法不同,但总的来说都是在像素之间增加了隔断,人们的大脑会趋向为这种断裂解释理由,自动为图像进行内部平滑处理。这就和我们凑近屏幕看游戏画面但是不会觉得画面模糊的原因类似。另一方面,因为扫描线的存在,画面的层次感也可以体现出来,使得画面更加可信。甚至连Her Story中都为了剧情的需要用些crt效果。
    这篇文章里介绍了大量的post processing shader,很有借鉴意义。
     

    一个shader的实现思路

    本文的后期特效将主要适用于前面所述的第三种情况,也即通过临近采样的方式放大图像而达到加强像素化的目的。更多的模拟LCD屏幕而不是CRT屏幕,所以一些包括屏幕扭曲,通道分离的效果在本文中将不会涉及。本文会利用psp模拟器,将扫描线效果应用到Tactics Ogres(中文译为:皇家骑士团)上。
    我主要从两方面完成对像素图的画面增强:1.利用微小的分割线来分隔开像素,让人们产生像素相连的错局。2.利用低通滤波器稍许的平滑像素边界(但是不宜平滑太多,不然会失去像素风格的特点)

    为了统一,后面的演示代码都用CG来写,输入的纹理尺寸为512 x 384

    格子的分割

    硬分割

    首先,将像素放大了2倍之后,实际看到的一个“像素 pixel”(叫纹素 texel更为贴切)是2 x 2个像素。虽然我们想营造出的效果是让玩家觉得游戏的像素与像素之间产生了间距,但除了在原先的一个像素上通过勾画边缘来实现分割,我们并不能真的将像素之间创造出空格。这步操作之后,最小单位仍然是像素。下图所示的分别是每2个像素进行一次分割和每4个像素进行一次分割的图示。

    每2格有一个明暗变化周期

    每4格有一个明暗变化周期

    对于后期特效来说,输入的纹理为camera input,上图是1 texel对应 4 pixel,而下面是1 texel对应 16 pixel。
    为了找到分割的位置,需要能够区分一个纹素所对应的像素。方法并不复杂, 若一个纹素拆分为4*4个像素,可以在顶点着色器上输出如下vec2:

    o.pixel_no = float2(o.uv.x * _MainTex_TexelSize.z, o.uv.y * _MainTex_TexelSize.w) * 0.25;

    _MainTex_TexelSize 是内置uniform,记录输入纹理的相关信息,其中zw分量即为宽和高。对于ppsspp模拟器,可以通过 u_texelDelta 来计算屏幕的resolution,后面会提到。
    有了pixel_no的信息,我们就可以在片段着色器里进行插值了:

    fixed4 Pass_Scanline(float2 uv) {
            float column = 4;
            float2 pixel_no = 
                frac(float2(uv.x * 1024.0, uv.y * 768) * _ScreenScale / column);
            if(pixel_no.x < 1 / column || pixel_no.y < 1 / column)
                return PREVIOUS_PASS(uv) * 0.5;
            else
                return PREVIOUS_PASS(uv);
    }

    其中PREVIOUS_PASS是一个宏,用来嵌套伪multi-pass,这里的PREVIOUS_PASS可以简单的理解为上一个获取纹理的值的pass。这里当column为4的时候,一个纹素对应的四个像素的pixel_no的x分量分别为1/8, 3/8, 5/8, 7/8,我们可以利用这个信息来判断究竟哪个像素是这个纹素的边缘。
    硬分割虽然完成了对像素的分割,但是效果比较生硬。玩家感受到的不是从屏幕上反映的图像,而更像是罩上了网格的图像。这也和asset store上的这个效果类似。

    丰富分割细节

    硬分割的效果不理想,于是很自然的想到为这个边缘添加一些过渡效果是否会好一点呢?答案是肯定的。另外,为了能取得比较好的过渡效果,我们应该适当提高pixel对texel的比例,测试下来发现一般来说3比较合适,2的话太窄,而4的话,图像放大的过大。
    为了理解方便,我们将图像的边缘定义为暗,图像的中央定义为亮,这样明暗间隔就能产生所谓的扫面线。问题演变为在一个纹素所对应的所有像素中,如何找到一个亮与暗的分布,从而表现出一个荧光格子的效果
    如果单纯的亮度从中心开始,依照切比雪夫距离向边缘递减,效果其实不太理想,纹素与纹素之间割裂的依旧生硬

    所以我们想找到一种方式柔滑这一过程,首先可以尝试用高斯平滑来处理

    卷积核
    简单的过渡不够,所以需要找到一个卷积核(kernel)来将像素周围的情况考虑进去,最常见的低通滤波器就是高斯滤波器(Gaussian Filter)但直接使用的话,会造成画面均匀平滑。Themaister提供了一个很好的思路(虽然由于git目录失效,原始的代码已经不可考,但是我还是在网上找到了一个GLSL版本 ),效果如下图所示:

    他的思路简单概述起来就是,一组像素(如4x4)向所在纹素的相邻8个纹素取样,权重为该像素到纹素距离倒数的负相关。本质上是一个非对称的低通滤波器。它的优势在于,针对每个纹素内的像素,所采样的纹素是一致的(保留了像素的质感)而在纹素内部,利用非对称的卷积核实现亮度的变化。

    一个纹素被分为9个像素

    取左上角的像素演示,红色的线条的长度与权重成负关系

    我们知道越靠近中间,加权值越高,对于一个靠左下角的像素来说,将其卷积核画出来可能会像这样:

    权重为Exp(-2.05 * 平方欧氏距离)

    权重为Exp(-2.05 * 平方欧氏距离)

    之所以不选择平方欧氏距离,是因为这会造成加权之后,中间亮度区分不开来,而周围的亮度又太低,会有种硬分割的感觉。
    在对周围的采样做了积分之后可以得到下图。虽然和前面的图很像,这张图的意义和刚才的并不一样,它代表的是一个纹素内的亮度分布(假设亮度的原始分布均匀)。

    考虑到以上的操作局限在一个很小的范围内,所以我们可以将其离散化后观察

    顶部看更直观

    一些细节

    滤波器的构成

    Themaister的方法中,考虑了亮度对像素最终颜色的影响,这个滤波器由两个函数构成,一个是空间域上的滤波器系数,另一个是值域(亮度)上的系数。如果采样点上的亮度越亮,意味着它将会更多的侵蚀着其他的像素。有关Glow效果,可以参考这篇文章

    float color_bloom(float3 color)
    {
        // const float3 gray_coeff = float3(0.30, 0.59, 0.11);
        const float shine = 0.25;
        float bright = Luminance(color);//dot(color, gray_coeff);
        return lerp(1.0 + shine * 0.5, 1.0 - shine, bright);
    }

    这里我们除了可以自己定义gray_coeff以外,我们也可以使用unity中的内置函数,它对应的 gray_coeff为fixed3(0.22, 0.707, 0.071)
    另外,通过在lerp的时候增加一个系数,我将暗部的亮度稍微提高了下,弥补曝光不足的情况。

    No.的偏移

    刚才的卷积核只是一个理想状态的演示,实际上,由于任意两个纹素是相邻的,所以只能在一个纹素的两边(看成一个正方形)上进行边的绘制。否则,两个相邻纹素在交界处都绘上黑边会导致扫描线过粗。另外,如果直接采样,将会出现平顶的情况,也即是当边上为偶数个像素的时候,中间会出现高度一样的状况。于是需要对之前的pixel_no进行偏移,偏移之后将会打破原有的平衡,找到一个新的中心。这里的偏移值应该小于1/(column * 2),否则循环周期将会出问题。

    float delta = dist(frac(pixel_no + float2(-0.125, 0.125)), offset + float2(0.5, 0.5));

    通过对比可以看出,偏移之后,左侧和上侧的亮度明显变暗,亮度会表现的更集中在中间的一个点。

    图为不同颗粒下的表现

    采样的偏移

    为了给物体增加一些投影,特别是文字,会对当前像素点的周围采样。我们并不是直接用相邻像素采样(相邻像素很有可能来自于同一纹素,所以采样没有意义),而是偏移一段距离,这和ps中的投影是一个原理。只是这里需要特别注意一个问题,也即是之前看到的一张图中出现的黑边问题。

    注意人物轮廓周围的黑边

    这个问题的起因是:如果采样点之间始终距离为一个纹素的时,虽然能保证取到的都是周围的纹素,但当图像中文本的边界正好是处于格子的边缘(也就是亮度最低的位置)在经历一个周期后,亮度是最低的地方(周期性所致)就会对之前还在暗色边界范围内的像素采样,这样就会出现在一个白的背景上出现了一条黑边。
    解决方法就是将采样偏移限制在纹素所包含的像素个数之内,虽然这意味着我们的投影无法超过一个纹素,但是起码会避免一些比较糟糕的情况。

    欧氏距离与曼哈顿距离的选择

    前面在谈到权重的时候,我们的图示标注出来的是欧几里得距离,那么如果为了将指令减少几条,变成曼哈顿距离如何呢?结果是:并不好

    可以看出,形成了一个明显的十字亮斑,并且高度差异并区分度不高

    另外值得一提的是,由于编译器和显卡的优化,使用曼哈顿距离并不能节省什么开销。

    增加bloom

    Bloom能起到加光晕的效果,能进一步降低粗糙感。通常来说,bloom只是作为HDR的一环,过程还可以包括Tone Mapping、Bright Pass Filter以及Blur。但由于我们这里只考虑2D的情况,更多时候HDR可以由美术手工实现,所以我们先不讨论ToneMapping而简单实现Bright和Blur。

    1 混合横向的bloom和纵向的bloom
    比较常见的bloom中的blur过程分为两次,一次横向像素上的模糊,一次纵向像素上的模糊,两次叠加。但是我们为了省力,也可以在一个pass中进行,毕竟我们只是为了虚化边缘,制造投影的效果。

    fixed4 Pass_SimpleBloom(float2 uv)
    {
        float4 sum = float4(0, 0, 0, 0);
        float4 bum = float4(0, 0, 0, 0);
        
        float2 glareSize = float2(1.0 / 512, 1.0 / 384) * 0.65;
        int height = 3;
        int width = 1;
        for(int i = -width; i < width; i++)
        {
            for(int j = -height; j < height; ++j)
            {
                sum += tex2D(_MainTex, uv + float2(i, j) * glareSize);
                bum += tex2D(_MainTex, uv + float2(j, i) * glareSize);
            }
        }
        fixed4 color = PREVIOUS_PASS(uv);
        color = (sum*sum*0.001 + bum*bum*0.0080) * _Amount / ((2* height +1) *(2* width +1)) + color*_Power;
        return color;
    }

    renderTexture与multipass

    Bloom的操作我并没有在ppsspp模拟器中实施,主要原因是我不知道如何在ppsspp中实现真正的multi-pass shader,如果只是通过宏将pass折叠起来,由于bloom需要对周围采样,将会导致计算量指数式上涨。
    但是这一切在unity中就很容易解决了,只需要在第一遍的pass中将bloom后的输出输出到render texture就可以被后面的shader所利用,两者加起来的时间测试下来大概只有single-pass的1/5,优化效果还是非常明显的。

    RenderTexture rtTemp = RenderTexture.GetTemporary(src.width, src.height);
    Graphics.Blit(src, rtTemp, _Material_1);
    Graphics.Blit(rtTemp, dst, _Material_2);
    RenderTexture.ReleaseTemporary(rtTemp);

    优化之前几乎所有消耗都耗在最后一个DrawIndexed上

    可以看出分割出两个pass之后开销一下平衡很多。另外,unity中在利用RenderTexture.GetTemporary时,内部会调用DiscardContents ,因而对CPU的效率也有所提升。详情可以参考官方文档
    增加了bloom之后的效果图。

    其他可能的改进

    投影增强

    前面我们在进行扩散投影模拟的时候,是同时对周围八个点进行采样,但是事实上,有时为了控制投影的方向,可以只对一侧的点进行采样

    如图所示,只需要对右下角的五个格子采样,就可以模拟出左上角的光照。

    这样造成的效果是亮的部分会凸起,暗的部分会产生凹陷的效果

    函数的拟合

    前面在计算相邻点的加权颜色值时,用到了一个指数函数。指数函数的效果的确很好,考虑到在某些平台上exp的消耗可能有点大。另外,任意两个像素之间的欧几里得距离不会超过2.3个像素,所以我们尝试对函数进行一个拟合,如0.926+1.441x + 0.6578x^2 + 0.0417x^4

    其实我们还可以将把它化成1/(7x^2 +1),效果也还可以,只是无论是哪种情况,在PC上测试差距并不明显(也有可能适得其反)

    扫描线

    考虑到有些游戏中,会出现一些因为曝光过度而无法显示扫描线的情况。于是,我们就需要对扫描线进行加强:

    float limit = 1 - step(257.0, min(frac(i.pixel_no.x), 1- frac(i.pixel_no.y)) * _MainTex_TexelSize.z);
    float bright = Luminance(out_color);
    return fixed4(out_color *(1.8 - limit * bright * bright * 0.89), 1.0);

    但是对于某些偏暗的游戏,如果为了提高整体亮度,而扫描线同时也强化的很厉害,那么就会导致“碳化”

    中间的白色由于亮度过高,在补偿的时候会显得非常暗

    虽然这样的扫描线加强在其他场合正是我们需要的,但在这里只会让画面变得很脏。关于这个问题并没有很好的解决方案,这需要根据不同游戏对参数做出调整。作为游戏开发,如果美术风格及早的确定,颜色的选择有所参照,将会对程序的优化有极大的帮助。而2D像素游戏由于很少受光照影响,再加上像素画本身也极其依赖于palette,所以如果palette控制的好,是可以根据其调试出一个很好的状态的。

    由于目前只用针对一款游戏,所以上面的手工调整可以接受。如果我们需要大量的调整,我在想,可能还有一种思路是像tone mapping一样,将亮度映射在一个合理的区域内,这样既保留了细节又处理了边界状况。

    Tactics Ogre的特殊处理

    刚开始我为Taactic Ogre(中文译为:皇家骑士团)写shader的时候,出现了一个问题。由于很容易知道psp的分辨率是480*272,我就将其硬编码到shader中。但是却出现了一些意想不到的状况。在横坐标方向上,扫描线的分布不均匀。由于是周期性的,并且随着窗口的扩大问题更为严重,我最开始猜测是模拟器的精度出现了问题,我查了下changelog也的确提到了这个问题,只是我使用的版本应该已经修复了这个问题。另外,我测试了其他的游戏,发现一切都很正常,如果真的是精度问题,不该只出现在这一款游戏上。查看了整个render过程后发现Tactics Ogre中有些地方与其他游戏做的不同,比如

    注意纹理右侧的黑边

    Tactics Ogre在draw顶部的滚动文本时,并不会对其裁剪,而是放到了第二个color pass里才进行裁剪

    不过ppsspp模拟器提供了u_texelDelta这样一个uniform,我们可以利用它得知当前输入纹理的resolution:

    vec2 c_resolution = 1.0f / u_texelDelta;

    这样,即使在某些场景中,屏幕的分辨率发生变化,我们也能够保证显示正确的扫描线。
     

    最终PSP模拟器效果图

    在这里给出自己制作的在PSP模拟器上的最终效果,请放大后观察

    结语

    本文主要讨论了针对细像素游戏的画质增强,但是这并不意味着像素游戏的增强方式只有一种,相反,光是这里 就提到多种后期特效。我们也无法说哪种效果比另一种更好。更多的时候,还是需要根据对游戏的定位来定制自己的后期特效,从而让画面为游戏核心服务。程序和美术之间的沟通是否充分也是能否有效的构建出成功的游戏画面中很重要的一个因素。

    最后,你们觉得这是一篇讨论像素游戏中画面增强的文章吗?
    不,不是的,我只是在安利Tactics Ogre :P

    展开全文
  • 每次打开新标签时都会获得像素游戏不同的高清壁纸。这个新主题除此以外还包括天气,时间,记事本,时钟等其他你想要的强大功能。 像素游戏是基于当今的技术水平,依然用像素风格来处理图像,强调清晰的轮廓、明快的...
  • Humble的慈善包,包含了几组像素风的武器素材(刀剑弓必收斧头药水等等)
  • 今天06年1月22日,刚从unity官方下载的2d像素游戏实例程序,新鲜出炉 为那些不方便下载的同学共享一下, 也为了赚点积分,下载自己想要的东西。 积分当做是搬运幸苦费吧,多谢啦。 我的工程是5.2.4f1,觉得是比较...
  • 用pygame写像素游戏地图编辑器

    千次阅读 2020-01-23 22:54:58
    用pygame写像素游戏地图编辑器 像素游戏的地图 我使用一个矩阵来存储地图,像下面这样: [[1,0,0],[0,1,0],[1,2,0]] 不同的数字代表不同的物体,比如1代表一个房子,0代表路面。 不同区间之间的物体的类型不同,比如...

    用pygame写像素游戏地图编辑器

    像素游戏的地图

    我使用一个矩阵来存储地图,像下面这样:
    [[1,0,0],[0,1,0],[1,2,0]]
    不同的数字代表不同的物体,比如1代表一个房子,0代表路面。
    不同区间之间的物体的类型不同,比如

    区间类型
    <1代表路面、草坪等可以通过的地方
    ≥1且<2代表墙面、等
    ≥2代表可以交互的地方

    功能

    创建后是这样的,按动按键可以改变下面的图片,点击上面的矩阵将上面的图片改变成下面的图片地图编辑器

    建立地图类

    初始化地图类
    我用一个字典self.dic 来保存地图的矩阵中的数对应储存地图图片,键是是储存的数,值是储存的文件名,self.dic_l则是用于字典的键的值便于后续对它操作,self.un_maps则是储存地图的矩阵。同时我还初始化了一个表面self.s_map用于绘制地图。

    class MapMaker:
    
        def __init__(self):
            """
            用字典来保存图片位置
            <1 代表路面、草坪等可以通过的地方
            ≥1且<2 代表墙面、等
            ≥2 代表可以交互的地方
            """
            self.dic = {0: "road", 0.1: "roadv", 0.11: "roadc1", 0.12: "roadc2", 0.13: "roadc3", 0.14: "roadc4",
                        0.15: "hospital_road2", 0.16: "hospital_road3",
                        0.2: "glass", 0.21: "hospital_f1", 0.22: "hospital_f2",
                        1: "wall", 1.1: "wallv", 1.11: "wallc", 1.12: "wallc1", 1.13: "wallc2", 1.14: "wallc3",
                        1.2: "hospital_wall1", 1.21: "hospital_wall2", 1.22: "hospital_wall3", 1.23: "hospital_wall4",
                        1.24: "hospital_wall5", 1.25: "hospital_wall6"}
            self.s_map = pygame.Surface(screen.get_size())
            self.s_map.fill([255, 255, 255])
            self.dic_l = list(self.dic)
    
            # 游戏地图 un_maps
            self.un_maps = [[1,0,0],[0,1,0],[1,2,0]]
    
    

    更新表面

    这个函数用于将表面更新到屏幕上。

        def r_show(self):
            # 再现地图
            screen.blit(self.s_map, (0, 0))
    

    绘制地图

    这个函数用于根据行列拆分地图,然后根据矩阵中每个元素的位置确定要绘制的地图的位置并更新表面。最后调用self.r_show()来更新显示。

        def get_map(self):
            # 放置下方的横条
            img_b = pygame.image.load(r"s\bang.png")
            self.s_map.blit(img_b, [0, -1])
            # 读取数组中位置的图片并更新
            ci, ri = 0, 0
            for c in self.un_maps:
                for r in c:
                    # 按行绘制
                    image = pygame.image.load(r"s\{}.png".format(self.dic[r]))
                    px, py = image.get_size()
                    self.s_map.blit(image, (ri * px, ci * py))
                    ri = ri + 1
                ci = ci + 1
                ri = 0  # 初始化行标识
                self.r_show()
    

    实现的效果是地图

    更新地图中的元素

    这个函数用于更新地图中的元素,需要元素的行索引、列索引和改变后的值

        def c_map(self, inx, iny, change):
            self.un_maps[iny][inx] = change
            self.get_map()
    

    显示当前的图像

    这个函数根据在字典中的顺序来显示当前值对应的文件名。

        def show_now(self, r):
            image = pygame.image.load(r"s\{}.png".format(self.dic[self.dic_l[r]]))
            self.s_map.blit(image, (100, 600))
            self.r_show()
    

    实现的效果
    下一个替换的图片

    储存地图文件

    保存在map.txt上

        def write_map(self):
            fo = open("map.txt", "w")
            fo.write(str(self.un_maps))
    

    初始化

    初始化地图类,并绘制地图
    设置一个变量now_talent用来保存当前位置的值。

    # 游戏初始化
    pygame.init()
    # 创建窗口
    screen = pygame.display.set_mode([1080, 720])
    screen.fill([255, 255, 255])
    pygame.display.set_caption("Map Maker")
    
    mp = MapMaker()
    mp.get_map()
    
    now_talent = 0
    

    处理事件

    下面用于获取鼠标的位置,并且如果鼠标按键动了,就更新鼠标所在位置元素块的图片。

    if event.type == pygame.MOUSEBUTTONDOWN:
                print(pygame.mouse.get_pos())
                x, y = pygame.mouse.get_pos()
                if x < 1080 and y < 540:
                    x, y = int(x / 36), int(y / 36)
                    mp.c_map(x, y, mp.dic_l[now_talent])
                    mp.show_now(now_talent)
    

    如果按动键盘按键,就更新索引值。

    if event.type == pygame.KEYDOWN:
                if now_talent < len(mp.dic_l) - 1:
                    now_talent = now_talent + 1
                    mp.show_now(now_talent)
                else:
                    now_talent = 0
                    mp.show_now(now_talent)
        pygame.display.update()
    

    完整代码

    import pygame
    
    
    # 本例用于完成二维像素地图的编辑
    
    
    class MapMaker:
    
        def __init__(self):
            """
            用字典来保存图片位置
            <1 代表路面、草坪等可以通过的地方
            ≥1且<2 代表墙面、等
            ≥2 代表可以交互的地方
            """
            self.dic = {0: "road", 0.1: "roadv", 0.11: "roadc1", 0.12: "roadc2", 0.13: "roadc3", 0.14: "roadc4",
                        0.15: "hospital_road2", 0.16: "hospital_road3",
                        0.2: "glass", 0.21: "hospital_f1", 0.22: "hospital_f2",
                        1: "wall", 1.1: "wallv", 1.11: "wallc", 1.12: "wallc1", 1.13: "wallc2", 1.14: "wallc3",
                        1.2: "hospital_wall1", 1.21: "hospital_wall2", 1.22: "hospital_wall3", 1.23: "hospital_wall4",
                        1.24: "hospital_wall5", 1.25: "hospital_wall6",
                        2: "hospital_home1", 2.1: "hospital_home2", 2.11: "hospital_home3", 2.12: "hospital_road1",
                        3: "SCUT"}
            self.s_map = pygame.Surface(screen.get_size())
            self.s_map.fill([255, 255, 255])
            self.dic_l = list(self.dic)
    
            # 游戏地图 un_maps
            self.un_maps = [[0.15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.25, 1, 0.21, 0.13, 1.22], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.21, 0.15, 2, 0.15, 1.21], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.21, 2, 2.1, 2.11, 1.21], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.21, 0.12, 2.12, 0.16, 1.21], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.24, 1.2, 0.16, 1.2, 1.23], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
    
        def get_map(self):
            # 放置下方的横条
            img_b = pygame.image.load(r"s\bang.png")
            self.s_map.blit(img_b, [0, -1])
            # 读取数组中位置的图片并更新
            ci, ri = 0, 0
            for c in self.un_maps:
                for r in c:
                    # 按行绘制
                    image = pygame.image.load(r"s\{}.png".format(self.dic[r]))
                    px, py = image.get_size()
                    self.s_map.blit(image, (ri * px, ci * py))
                    ri = ri + 1
                ci = ci + 1
                ri = 0  # 初始化行标识
                self.r_show()
    
        def r_show(self):
            # 再现地图
            screen.blit(self.s_map, (0, 0))
    
        def c_map(self, inx, iny, change):
            self.un_maps[iny][inx] = change
            self.get_map()
    
        def write_map(self):
            fo = open("map.txt", "w")
            fo.write(str(self.un_maps))
    
        def show_now(self, r):
            image = pygame.image.load(r"s\{}.png".format(self.dic[self.dic_l[r]]))
            self.s_map.blit(image, (100, 600))
            self.r_show()
    
    
    
    # 游戏初始化
    pygame.init()
    # 创建窗口
    screen = pygame.display.set_mode([1080, 720])
    screen.fill([255, 255, 255])
    pygame.display.set_caption("Map Maker")
    
    mp = MapMaker()
    mp.get_map()
    
    now_talent = 0
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                mp.write_map()
                # 退出游戏
                pygame.quit()
                break
            elif event.type == pygame.MOUSEBUTTONDOWN:
                print(pygame.mouse.get_pos())
                x, y = pygame.mouse.get_pos()
                if x < 1080 and y < 540:
                    x, y = int(x / 36), int(y / 36)
                    mp.c_map(x, y, mp.dic_l[now_talent])
                    mp.show_now(now_talent)
            elif event.type == pygame.KEYDOWN:
                if now_talent < len(mp.dic_l) - 1:
                    now_talent = now_talent + 1
                    mp.show_now(now_talent)
                else:
                    now_talent = 0
                    mp.show_now(now_talent)
        pygame.display.update()
    
    
    展开全文
  • 独立游戏像素中文字体,个人可使用;商用需要给原作者版权费。
  • 像素游戏素材RPGmaker系列美术资源

    千次阅读 2021-04-28 02:53:55
    像素风格类游戏制作以RPGmaker(简称RM)系列为主,或者说独立...如果你也深受同感,那么希望下面这些优秀精美的像素游戏素材资源能够给你提供帮助。 这类素材资源网上很少,以上希望能对你有帮助! 素材下载:

    像素风格类游戏制作以RPGmaker(简称RM)系列为主,或者说独立开发者和新人小白使用较多。毕竟软件门槛低,易上手等优点。相比于其它游戏引擎对于我们来说友好很多。不过还是有一点不太友好!

    那就是像素类游戏依然是相对小众的风格,对于初学者和独立开发者来说,在美术方面的可参考和学习就比较难,一些新人朋友想练习却没有满意的像素风素材资源可用,真的打击学习积极性。如果你也深受同感,那么希望下面这些优秀精美的像素游戏素材资源能够给你提供帮助。

    像素游戏生活模拟主题素材

    像素游戏城市地图
    村庄像素游戏场景地图
    RPGmaker像素游戏素材
    像素游戏素材平铺图块
    科幻风格像素游戏素材
    像素游戏图标
    像素游戏角色素材
    这类素材资源网上很少,以上希望能对你有帮助!
    素材下载:https://zyb99.lanzoui.com/iWmWYoktpng
    有新的在更新!

    展开全文
  • RPG像素游戏角色大合集

    千次阅读 2020-06-16 13:55:08
    2000多套像素游戏角色素材,人物NPC四方向行走图合集,PNG透明免扣动画序列文件。包含现代/古风/中世纪等多种角色风格。角色并非全部为人物,还有一些动物,怪物等适合作为敌人的角色。 下载地址:...

    2000多套像素类游戏角色素材,人物NPC四方向行走图合集,PNG透明免扣动画序列文件。包含现代/古风/中世纪等多种角色风格。角色并非全部为人物,还有一些动物,怪物等适合作为敌人的角色。

    下载地址:http://www.zyb99.cn/160

    展开全文
  • unity3d实现像素游戏的精确碰撞判定

    千次阅读 2019-08-13 07:39:03
    因为unity用的box2d的aabb碰撞触发范围比定义的范围要大,所以对于像素游戏来说,会有像素差,会影响实际画面,比如站在地上有时候会离地腾空1个像素高 况且像素游戏基本是方块判定,也用不太到什么摩擦力,反弹...
  • 像素鸟小游戏源代码

    2018-05-30 17:37:06
    用JAVA,swing写的小游戏哟,涉及到线程、IO流、窗口等知识。
  • 做课程用的一整套像素风Rpg素材,适合做独立游戏或学校作业 ·PSD/地图图块分层PSD文件 ·tileset/地图资源: 图块(草地、房屋、树木、宝箱、木桶、种植物、栅栏、河流、高地) ·spritesheets/人物图片: 英雄四方向...
  • 文件不包含预览图,只包含地图元素素材文件不包含预览图,只包含地图元素素材文件不包含预览图,只包含地图元素素材文件不包含预览图,只...可直接用于rpg maker mv制作游戏。 下载地址:https://zyb99.lanzous.com...
  • 本资源包内含有打造一款塔防游戏的所有基础物件,能够让你轻松开始创作自己的游戏。 资源包内拥有3种不同的塔: 骑士塔 -能够创建3位骑士 -能够提升骑士的伤害 -能够给骑士增加一个盾 -拥有一个能放置骑士的小旗 ...
  • 2D经典像素游戏 rougelike

    千次阅读 2018-01-17 02:45:09
    游戏介绍: 主人公在一个10*10方格中求生。 设定: 1、主人公每走一步消耗一点体力值。 2、主人公初始有10点体力值。 3、地图上会随机出现僵尸、补给品、障碍物。 4、主人公每走2步后僵尸行走一步。 5、如果...
  • 用原生js+html+css写一个像素鸟小游戏,按回车(enter)键开始/暂停游戏,按空格使小鸟向上飞,穿过钢管,获得胜利
  • Pixel.GameCenter是一个具有简单像素游戏的市场。 在这里您可以下载并玩流行的GBC和GB游戏。 联系人电子邮件:pixelstudioscompany@gmail.com
  • [Unity3D] 2D像素游戏(一) Hello Unity!

    万次阅读 多人点赞 2018-08-22 17:47:49
    引言 ...事先声明:这儿只是一位自得其乐的游戏开发爱好者的学习笔记,不追求绝对正确和优雅高效,但尽量保证简单易懂(怕自己以后也看不懂自己在写些什么),如果不小心误导了大家,那真是无意之举...
  • 像素生存 基于 Sprite Kit 的像素游戏
  • unity想要做像素游戏最好摄像机用正交视图(不排除可以用透视的) 这样里面就只有size可以调节,默认是5,就是半个屏幕的高度 注意这里的5是unity里单位距离,一个quad不进行缩放的情况下宽度就是1 plane的话不进行...
  • 像素地牢游戏 一个基于2D数组的基本地牢游戏,具有非常基本的像素艺术/动画。 作为DIG 3480的最终项目-计算机作为媒介。 在4天内创建。 最初要求游戏具有一个级别,但是此实现的独特之处在于,每次用户玩游戏时,...
  • party hard2 类型2D像素游戏3D化的游戏是用什么制作的 GameMaker Studio
  • 回顾 构思 素材准备 寻找地板和障碍素材 ...在初步认识了Unity之后,我们成功创建了第一个2D像素精灵——我们的主角Player,并且导入添加了一个LittleBuddy作为主角的载体。 构思 当我们打算继续的时候,会陷...
  • JavaScript(jquery)写的像素游戏贪吃蛇。设计理念:1.构成游戏的所有可见图形都是由正方形组成的;2.蛇的移动只根据方向改变蛇头部的下一个位置,其他身体部位全部移动到上一个部位。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 60,145
精华内容 24,058
关键字:

像素游戏